home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / kernel / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-02  |  71.7 KB  |  2,886 lines  |  [TEXT/KAHL]

  1. /* The main simulation-running code in Xconq.
  2.    Copyright (C) 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. /* This is the main simulation-running code. */
  11.  
  12. #include "conq.h"
  13.  
  14. extern int visible_to PROTO ((Unit *unit, Unit *unit2));
  15.  
  16. static void maybe_surrender_to PROTO ((Unit *unit, Unit *unit2));
  17.  
  18. static void run_turn_start PROTO ((void));
  19. static void run_restored_turn_start PROTO ((void));
  20. static void init_movement PROTO ((void));
  21. static void init_actionvector PROTO ((void));
  22. static void run_tech_leakage PROTO ((void));
  23. static void cache_init_tech_levels PROTO ((void));
  24. static void run_tooling_attrition PROTO ((void));
  25. static void reset_all_reserves PROTO ((void));
  26. static void compute_moves PROTO ((void));
  27. static int move_some_units PROTO ((int lim));
  28. static int unit_still_acting PROTO ((Unit *unit, int checkwaiting));
  29. static int move_one_unit_multiple PROTO ((Unit *unit, int lim));
  30. static void finish_movement PROTO ((void));
  31. static void test_agreements PROTO ((void));
  32. static void compute_sun PROTO ((void));
  33. static void run_sun PROTO ((void));
  34. static void compute_season PROTO ((void));
  35. static void run_environment PROTO ((void));
  36. static void damage_unit_with_temperature PROTO ((Unit *unit, int n));
  37. static void mix_winds PROTO ((void));
  38. static int spying_possible PROTO ((void));
  39. static void run_spies PROTO ((void));
  40. static void run_random_events PROTO ((void));
  41. static int init_accidents PROTO ((void));
  42. static void run_accidents PROTO ((void));
  43. static int init_attrition PROTO ((void));
  44. static void run_attrition PROTO ((void));
  45. static int init_revolts PROTO ((void));
  46. static void run_revolts PROTO ((void));
  47. static void unit_revolt PROTO ((Unit *unit));
  48. static int init_surrenders PROTO ((void));
  49. static void run_surrenders PROTO ((void));
  50. static void unit_surrender PROTO ((Unit *unit));
  51. static int excess_left PROTO ((int x, int y));
  52. static void try_transfer_to_cell PROTO ((int x, int y));
  53. static int sharable_left PROTO ((int x, int y));
  54. static void try_sharing_with_cell PROTO ((int x, int y));
  55. static void run_economy PROTO ((void));
  56. static int base_production PROTO ((Unit *unit, int m));
  57. static void try_transfer PROTO ((Unit *from, Unit *to, int r));
  58. static void try_sharing PROTO ((Unit *from, Unit *to, int m));
  59. static void try_transfer_aux PROTO ((Unit *from, Unit *to, int r));
  60. static int can_satisfy_need PROTO ((Unit *unit, int r, int need));
  61. static void run_turn_end PROTO ((void));
  62. static void run_people_consumption PROTO ((void));
  63. static void run_cell_consumption PROTO ((void));
  64. static void run_unit_base_consumption PROTO ((void));
  65. static void unit_consumes PROTO ((Unit *unit));
  66. static int in_supply PROTO ((Unit *unit, int m));
  67. static void run_self_builds PROTO ((void));
  68. static void run_people_side_changes PROTO ((void));
  69. static void update_cell_display_all_sides PROTO ((int x, int y, int rightnow));
  70. static void run_appearances PROTO ((void));
  71. static void run_disappearances PROTO ((void));
  72. static void run_hp_recovery PROTO ((void));
  73. static int season_effect PROTO ((int u));
  74. static void run_detonation_accidents PROTO ((void));
  75. static void run_people_limits PROTO ((void));
  76. static void maybe_detonate_accidently PROTO ((Unit *unit));
  77. static void spy_on_location PROTO ((int x, int y));
  78.  
  79. int num_people_at PROTO ((int x, int y));
  80.  
  81. /* The number of the current turn within a year. */
  82.  
  83. int curyearpart = -1;
  84.  
  85. /* The season name for the current turn. */
  86.  
  87. char *curseasonname = NULL;
  88.  
  89. /* This is the main array that tracks units acting during this turn. */
  90.  
  91. UnitVector *actionvector = NULL;
  92.  
  93. int curpriority = 0;
  94.  
  95. /* The table of all types of random events. */
  96.  
  97. struct randomeventtype {
  98.     int key;
  99.     int (*initfn) PROTO ((void));
  100.     void (*fn) PROTO ((void));
  101. } randomeventmethods[] = {
  102.     { K_ACCIDENTS_IN_TERRAIN, init_accidents, run_accidents },
  103.     { K_ATTRITION_IN_TERRAIN, init_attrition, run_attrition },
  104.     { K_UNITS_REVOLT, init_revolts, run_revolts },
  105.     { K_UNITS_SURRENDER, init_surrenders, run_surrenders },
  106.     { 0, NULL, NULL }
  107. };
  108.  
  109. int numrandomevents = 0;
  110.  
  111. int randomeventindices[10]; /* this must be >= number of diff methods */
  112.  
  113. int maintimeout = -1;
  114.  
  115. int paused = FALSE;
  116.  
  117. /* State variables. */
  118. /* (I don't think all of these are strictly necessary) */
  119.  
  120. /* This becomes TRUE the first time run_game is executed. */
  121.  
  122. int gameinited = FALSE;
  123.  
  124. /* This is true only before the game actually starts. */
  125.  
  126. int beforestart = TRUE;
  127.  
  128. /* This is true only at the beginning of a turn. */
  129.  
  130. int at_turn_start = FALSE;
  131.  
  132. /* This is true after the game is over. */
  133.  
  134. int endofgame = FALSE;
  135.  
  136. /* How often to do saves while playing. */
  137.  
  138. int checkpointinterval = 0;
  139.  
  140. /* This is set FALSE whenever the game state changes, and TRUE whenever
  141.    the game has been saved. */
  142.  
  143. int gamestatesafe = TRUE;
  144.  
  145. /* This is TRUE after the designer has been mucking around, or if
  146.    networked versions are found to be inconsistent. */
  147.  
  148. int compromised = FALSE;
  149.  
  150. /* True whenever the game has both day and night. */
  151.  
  152. int daynight = FALSE;
  153.  
  154. /* The location of the sun, as a position relative to the area.  The
  155.    actual values may be far outside the area. */
  156.  
  157. int sunx, suny;
  158.  
  159. /* The sun's previous location. */
  160.  
  161. int lastsunx = -1, lastsuny = -1;
  162.  
  163. /* The time at which the game actually starts. */
  164.  
  165. time_t game_start_in_real_time;
  166.  
  167. /* The point in the turn at which players can actually do things. */
  168.  
  169. time_t turn_play_start_in_real_time;
  170.  
  171. int planexecs;
  172.  
  173. int taskexecs;
  174.  
  175. int any_tooling_attrition = -1;
  176.  
  177. int any_self_builds = -1;
  178.  
  179. int any_appearances = -1;
  180.  
  181. int any_people_side_changes = -1;
  182.  
  183. int *any_people_surrenders = NULL;
  184.  
  185. int any_hp_recovery = -1;
  186.  
  187. int any_tech_leakage = -1;
  188.  
  189. int any_detonation_accidents = -1;
  190.  
  191. int any_unit_production = -1;
  192.  
  193. int any_terrain_production = -1;
  194.  
  195. int any_people_production = -1;
  196.  
  197. int any_people_consumption = -1;
  198.  
  199. int any_cell_consumption = -1;
  200.  
  201. int any_unit_base_consumption = -1;
  202.  
  203. int any_people_max = -1;
  204.  
  205. int any_spying = -1;
  206.  
  207. int any_disappearances = -1;
  208.  
  209. /* This function does a (small, usually) amount of simulation, then returns.
  210.    It can be run multiple times at any time, will not go "too far".
  211.    It returns the max time in seconds that the interface should do
  212.    things before running this again. */
  213.  
  214. int
  215. run_game(maxactions)
  216. int maxactions;
  217. {
  218.     int numacted, othersdone, runtime;
  219.     time_t rungamestart, rungameend;
  220.     Side *side;
  221.  
  222.     gameinited = TRUE;
  223.     time(&rungamestart);
  224.     if (beforestart) {
  225.     /* If we haven't started yet, see if it's time. */
  226.     test_for_game_start();
  227.     Dprintf("run_game: tested for game start.\n");
  228.     } else if (endofgame) {
  229.     /* Nothing to do except wait for users to do exit commands. */
  230.         Dprintf("run_game: at end of game.\n");
  231.     } else if (paused) {
  232.     /* Don't do anything if we're paused. */
  233.         Dprintf("run_game: paused.\n");
  234.     } else {
  235.     if (at_turn_start) {
  236.         if (midturnrestore)
  237.           run_restored_turn_start();
  238.         else
  239.           run_turn_start();
  240.         check_all_units();
  241.         compose_actionvector();
  242.         init_movement();
  243.         update_all_progress_displays("", -1);
  244.         /* Game might have been ended by new turn init. */
  245.         if (endofgame) {
  246.             Dprintf("run_game: game ended by new turn init.\n");
  247.             return 0;
  248.         }
  249.         time(&turn_play_start_in_real_time);
  250.         at_turn_start = FALSE;
  251.     }
  252.     for_all_sides(side) {
  253.         /* If this is running in realtime, update all clock displays. */
  254.         if (side->ingame && side_has_display(side) && realtime_game()) {
  255.         update_clock_display(side, TRUE);
  256.         }
  257.         /* Non-participating sides are automatically "finished". */
  258.         if (side->ingame
  259.             && !side->finishedturn
  260.         && !side_has_ai(side)
  261.         && !side_has_display(side)) {
  262.         Dprintf("run_game: %s finished - no AI and/or display.\n",
  263.             side_desig(side));
  264.         finish_turn(side);
  265.         }
  266.     }
  267.     /* If all sides are done acting, end the turn.  This won't be true
  268.        right at the start of a turn. */
  269.     if (all_sides_finished() || exceeded_rt_per_turn()) {
  270.         run_turn_end();
  271.         Dprintf("run_game: at turn end.\n");
  272.         at_turn_start = TRUE;
  273.     } else {
  274.         /* Move some units around. */
  275.         numacted = move_some_units(maxactions);
  276.         othersdone = TRUE;
  277.         for_all_sides(side) {
  278.         if (!side->finishedturn) {
  279.             /* Display and/or AI might have vanished? */
  280.             if (!side_has_ai(side) && !side_has_display(side)) {
  281.                 Dprintf("run_game: %s finished - AI and/or display gone.\n",
  282.                 side_desig(side));
  283.             finish_turn(side);
  284.             }
  285.             /* See if any sides auto-finish. */
  286.             if (!units_still_acting(side)
  287.             && side->autofinish
  288.             && !side->designer) {
  289.                 Dprintf("run_game: %s auto-finishes.\n", side_desig(side));
  290.             finish_turn(side);
  291.             }
  292.         }
  293.         if (!side->finishedturn && side_has_display(side)) {
  294.             othersdone = FALSE;
  295.         }
  296.         }
  297.         if (numacted == 0 && othersdone) {
  298.         for_all_sides(side) {
  299.             if (!side->finishedturn
  300.             && side_has_ai(side)
  301.             && !side_has_display(side)) {
  302.             Dprintf("run_game: %s can't think of what to do, finishes.\n",
  303.                 side_desig(side));
  304.             finish_turn(side);
  305.             }
  306.         }
  307.         }
  308.         if (Debug) {
  309.             Dprintf("run_game: ");
  310.         switch (maxactions) {
  311.           case -1:
  312.             Dprintf("%d actions.", numacted);
  313.             break;
  314.           case 0:
  315.             Dprintf("No actions.");
  316.             break;
  317.           case 1:
  318.             Dprintf("%d/1 action.", numacted);
  319.             break;
  320.           default:
  321.             Dprintf("%d/%d actions.", numacted, maxactions);
  322.             break;
  323.         }
  324.         if (planexecs > 0)
  325.           Dprintf(" (%d plan execs)", planexecs);
  326.         if (taskexecs > 0)
  327.           Dprintf(" (%d task execs)", taskexecs);
  328.         /* (also number of units considered?) */
  329.             Dprintf("\n");
  330.         }
  331.     }
  332.     check_realtime();
  333.     test_for_game_end();
  334.     }
  335.     time(&rungameend);
  336.     runtime = idifftime(rungameend, rungamestart);
  337.     if (runtime > 0)
  338.       Dprintf("run_game: took %d seconds\n", runtime);
  339.     return 0;
  340. }
  341.  
  342. /* See if game is ready to get underway for real.  Note that displays will
  343.    work before the game has started, but game time doesn't move. */
  344.  
  345. void
  346. test_for_game_start()
  347. {
  348.     int anydisplays = FALSE;
  349.     Side *side;
  350.  
  351.     /* We must have at least one unit, on a side that is being displayed,
  352.        before the game can start for real. */
  353.     for_all_sides(side) {
  354.     if (side_has_display(side)) {
  355.         anydisplays = TRUE;
  356.     }
  357.     if (side_has_units(side) && side_has_display(side)) {
  358.         /* Now we're really ready to roll. */
  359.         beforestart = FALSE;
  360.         at_turn_start = TRUE;
  361.         if (midturnrestore)
  362.           record_event(H_GAME_RESTARTED, ALLSIDES);
  363.         else
  364.           record_event(H_GAME_STARTED, ALLSIDES);
  365.         /* Record the game as starting NOW in real time. */
  366.         time(&game_start_in_real_time);
  367.         /* No need to look at any more sides, just get on with the game. */
  368.         return;
  369.     }
  370.     }
  371.     if (!anydisplays) {
  372.     init_warning("No sides have a display");
  373.     }
  374. }
  375.  
  376. /* This routine looks to see if the game is completely over. */
  377.  
  378. void
  379. test_for_game_end()
  380. {
  381.     Side *side;
  382.  
  383.     /* Declare a draw if everybody is amenable. */
  384.     if (all_others_willing_to_quit(NULL)) {
  385.         /* (should remove all sides first?) */
  386.     end_the_game();
  387.     }
  388.     for_all_sides(side) {
  389.         /* If we have an active side being displayed, we're not done yet. */
  390.     if (side->ingame && side_has_display(side))
  391.       return;
  392.     /* (If no displayed sides have units, turns will whiz by) */
  393.     }
  394.     end_the_game();
  395. }
  396.  
  397. #if 0
  398.     /* Add this time interval to all sides's time consumption. */
  399.     for_all_sides(side) {
  400.         int delta_time = (time(0) - side->lasttime);
  401.  
  402.         if (side->more_units) {
  403.         side->timeleft -= delta_time;
  404.         side->timetaken += delta_time;
  405.         update_clock_display(side, TRUE);
  406.         }
  407.     }
  408. #endif
  409.  
  410.  
  411. /* This is true when all participating sides have finished their turn. */
  412.  
  413. int
  414. all_sides_finished()
  415. {
  416.     Side *side;
  417.  
  418.     for_all_sides(side) {
  419.     if (side->ingame && !side->finishedturn) {
  420.         return FALSE;
  421.     }
  422.     }
  423.     return TRUE;
  424. }
  425.  
  426. /* Call this from interfaces to check on realtime details without actually
  427.    going into run_game.  Will call back to interface if necessary. */
  428.  
  429. void
  430. check_realtime()
  431. {
  432.     Side *side;
  433.  
  434.     if (!realtime_game())
  435.       return;
  436.     if (exceeded_rt_for_game())
  437.       end_the_game();
  438.     if (g_rt_per_side() > 0) {
  439.     for_all_sides(side) {
  440.         if (side->ingame && side->totaltimeused > g_rt_per_side()) {
  441.         remove_side_from_game(side);
  442.         }
  443.     }
  444.     }
  445. }
  446.  
  447. int
  448. exceeded_rt_for_game()
  449. {
  450.     time_t now;
  451.  
  452.     if (g_rt_for_game() <= 0)
  453.       return FALSE;
  454.     time(&now);
  455.     return (idifftime(now, game_start_in_real_time) + g_elapsed_time() > g_rt_for_game());
  456. }
  457.  
  458. int
  459. exceeded_rt_per_turn()
  460. {
  461.     time_t now;
  462.  
  463.     if (g_rt_per_turn() <= 0)
  464.       return FALSE;
  465.     time(&now);
  466.     return (idifftime(now, turn_play_start_in_real_time) > g_rt_per_turn());
  467. }
  468.  
  469. /* This returns true if the given side is still wanting to do stuff. */
  470.  
  471. int
  472. units_still_acting(side)
  473. Side *side;
  474. {
  475.     Unit *unit;
  476.  
  477.     if (side->ingame) {
  478.     for_all_side_units(side, unit) {
  479.         if (unit_still_acting(unit, FALSE)) {
  480.         return TRUE;
  481.         }
  482.     }
  483.     }
  484.     return FALSE;
  485. }
  486.  
  487. /* Do everything that would happen before movement in a turn. */
  488.  
  489. static void
  490. run_turn_start()
  491. {
  492.     int curturn;
  493.     time_t turncalcstart, turncalcend;
  494.     Side *side;
  495.  
  496.     /* Increment the turn number. */
  497.     curturn = g_turn();
  498.     ++curturn;
  499.     set_g_turn(curturn);
  500.     /* See if we've hit the preset end of the game. */
  501.     if (curturn > g_last_turn() && !probability(g_extra_turn())) {
  502.     end_the_game();
  503.     /* The game is over, don't bother with the other calcs. */
  504.     return;
  505.     }
  506.     time(&turncalcstart);
  507.     update_all_progress_displays("turn start calcs", -1);
  508.     compute_season();
  509.     Dprintf("##### TURN %d (%s) #####\n",
  510.         curturn, absolute_date_string(curturn));
  511.     for_all_sides(side) {
  512.     side->finishedturn = FALSE;
  513.     update_turn_display(side, TRUE);
  514.     if (realtime_game()) {
  515.         update_clock_display(side, TRUE);
  516.     }
  517.     }
  518.     run_sun();
  519.     run_environment();
  520.     run_economy();
  521.     run_hp_recovery();
  522.     run_self_builds();
  523.     run_appearances();
  524.     run_random_events();
  525.     run_detonation_accidents();
  526.     sort_units();
  527.     init_actionvector();
  528.     curpriority = 0;
  529.     compute_moves();
  530.     run_spies();
  531.     run_tech_leakage();
  532.     run_tooling_attrition();
  533.     cache_init_tech_levels();
  534.     reset_all_reserves();
  535.     gamestatesafe = FALSE;
  536.     if ((checkpointinterval > 0) && (curturn % checkpointinterval == 0)) {
  537.     write_entire_game_state(checkpoint_filename());
  538.     }
  539.     time(&turncalcend);
  540.     Dprintf("%d seconds to calc at turn start\n",
  541.         idifftime(turncalcend, turncalcstart));
  542. }
  543.  
  544. /* Do computations to start the first turn of a restored game. */
  545.  
  546. static void
  547. run_restored_turn_start()
  548. {
  549.     Side *side;
  550.  
  551.     Dprintf("##### TURN %d (%s) #####\n",
  552.         g_turn(), absolute_date_string(g_turn()));
  553.     for_all_sides(side) {
  554.     update_turn_display(side, TRUE);
  555.     if (realtime_game()) {
  556.         update_clock_display(side, TRUE);
  557.     }
  558.     }
  559.     compute_sun();
  560.     sort_units();
  561.     init_actionvector();
  562.     /* We can set the priority arbitrarily now, since calculations will
  563.        shortly move it to the correct value. */
  564.     curpriority = 0;
  565.     /* We're done with restore-specific tweaks, turn the flag off. */
  566.     midturnrestore = FALSE;
  567. }
  568.  
  569. static void
  570. init_actionvector()
  571. {
  572.     if (actionvector == NULL)
  573.       actionvector = make_unit_vector(max(numunits * 2, 100));
  574.     clear_unit_vector(actionvector);
  575. }
  576.  
  577. static void
  578. init_movement()
  579. {
  580.     int i;
  581.     Side *side, *side2;
  582.  
  583.     for_all_sides(side) {
  584.     if (side->ingame) {
  585.         /* No units are waiting for orders initially. */
  586.         side->numwaiting = 0;
  587.     }
  588.     }
  589.     i = 0;
  590.     for_all_sides(side) {
  591.     side->turnstarttime = time(0);
  592.     /* Didn't really do input, but useful to pretend so. */
  593.     side->lasttime = time(0);
  594.     if (g_use_side_priority())
  595.       side->priority = i++;
  596.     if (side_has_ai(side))
  597.       ai_init_turn(side);
  598.     side->busy = FALSE;
  599.     if (side_has_display(side))
  600.       update_action_display(side, TRUE);
  601.     }
  602.     /* Inform sides with displays that all units are ready to act. */
  603.     for_all_sides(side) {
  604.     if (side_has_display(side)) {
  605.         for_all_sides(side2) {
  606.         update_side_display(side, side2, TRUE);
  607.         }
  608.     }
  609.     }
  610. }
  611.  
  612. /* Compute the leakage of technology from one side to another. */
  613.  
  614. static void
  615. run_tech_leakage()
  616. {
  617.     int u;
  618.     Side *side, *side2;
  619.  
  620.     if (any_tech_leakage < 0) {
  621.     any_tech_leakage = FALSE;
  622.     for_all_unit_types(u) {
  623.         if (u_tech_leakage(u) > 0) {
  624.         any_tech_leakage = TRUE;
  625.         break;
  626.         }
  627.     }
  628.     }
  629.     if (!any_tech_leakage)
  630.       return;
  631.     Dprintf("Running tech leakage\n");
  632.     for_all_sides(side) {
  633.     for_all_sides(side2) {
  634.         if (side != side2 /* and some contact between sides */) {
  635.         for_all_unit_types(u) {
  636.             if (side->tech[u] < side2->tech[u]
  637.             && u_tech_leakage(u) > 0) {
  638.             side->tech[u] += prob_fraction(u_tech_leakage(u));
  639.             }
  640.         }
  641.         }
  642.     }
  643.     }
  644. }
  645.  
  646. /* Remember each side's tech levels before it does any research actions
  647.    during the turn.  This can be used to keep tech level from going up too
  648.    fast if the player has lots of units doing research. */
  649.  
  650. static void
  651. cache_init_tech_levels()
  652. {
  653.     int u;
  654.     Side *side;
  655.  
  656.     if (using_tech_levels()) {
  657.     for_all_sides(side) {
  658.         for_all_unit_types(u) {
  659.         side->inittech[u] = side->tech[u];
  660.         }
  661.     }
  662.     }
  663. }
  664.  
  665. /* Reduce some units' construction tooling randomly. */
  666.  
  667. static void
  668. run_tooling_attrition()
  669. {
  670.     int u, u2, att;
  671.     Unit *unit;
  672.  
  673.     /* Test whether tooling attrition is ever possible. */
  674.     if (any_tooling_attrition < 0) {
  675.     any_tooling_attrition = FALSE;
  676.     for_all_unit_types(u) {
  677.         for_all_unit_types(u2) {
  678.         if (uu_tp_attrition(u, u2) > 0) {
  679.             any_tooling_attrition = TRUE;
  680.             break;
  681.         }
  682.         }
  683.         if (any_tooling_attrition)
  684.           break;
  685.     }
  686.     }
  687.     if (!any_tooling_attrition)
  688.       return;
  689.     for_all_units(unit) {
  690.     if (is_active(unit) && unit->tooling != NULL) {
  691.         for_all_unit_types(u2) {
  692.         att = uu_tp_attrition(unit->type, u2);
  693.         if (att > 0) {
  694.             unit->tooling[u2] -= prob_fraction(att);
  695.         }
  696.         if (unit->tooling[u2] < 0) unit->tooling[u2] = 0;
  697.         }
  698.     }
  699.     }
  700. }
  701.  
  702. static void
  703. reset_all_reserves()
  704. {
  705.     Unit *unit;
  706.  
  707.     for_all_units(unit) {
  708.     if (unit->plan != NULL) {
  709.         unit->plan->reserve = FALSE;
  710.     }
  711.     }
  712. }
  713.  
  714. /* Compute moves and actions for all the units at once, put everybody that
  715.    can do anything into a list. */
  716.  
  717. static void
  718. compute_moves()
  719. {
  720.     int curturn = g_turn();
  721.     Unit *unit;
  722.     Side *side;
  723.  
  724.     for_all_sides(side) {
  725.     side->numacting = 0;
  726.     side->numfinished = 0;
  727.     for_all_side_units(side, unit) {
  728.         if (unit->act) {
  729.         /* Unit acp is set to -1 to indicate uninitialization,
  730.            but acp is computed by adding to the previous acp,
  731.            so when starting a new game (as opposed to
  732.            restoring an old one), acp should be inited to
  733.            zero.  (This could maybe be done better.) */
  734.         if (curturn == 1)
  735.           unit->act->acp = 0;
  736.         compute_acp(unit);
  737.         update_unit_acp_display(side, unit, FALSE);
  738.         }
  739.     }
  740.     }
  741. }
  742.  
  743. void
  744. compose_actionvector()
  745. {
  746.     Unit *unit;
  747.  
  748.     for_all_units(unit) {
  749.     if (unit->act && unit->act->initacp > 0 && unit_priority(unit) == curpriority) {
  750.         actionvector = add_unit_to_vector(actionvector, unit, 0);
  751.         /* Clear all delay flags. */
  752.         if (unit->plan)
  753.           unit->plan->delayed = FALSE;
  754.     }
  755.     }
  756.     Dprintf("Action vector has %d units, at priority %d\n",
  757.         actionvector->numunits, curpriority);
  758. }
  759.  
  760. int
  761. unit_priority(unit)
  762. Unit *unit;
  763. {
  764.     if (unit->side)
  765.       return unit->side->priority;
  766.     return 0;
  767. }
  768.  
  769. /* Compute the action points available to the unit this turn. */
  770.  
  771. void
  772. compute_acp(unit)
  773. Unit *unit;
  774. {
  775.     int u = unit->type, t, acp, maxacp, minacp;
  776.     Obj *dmgeffect;
  777.     Unit *occ;
  778.  
  779.     /* Units still under construction or off-area can't do anything. */
  780.     if (!completed(unit) || !inside_area(unit->x, unit->y)) {
  781.     unit->act->initacp = unit->act->acp = unit->act->actualactions = 0;
  782.     return;
  783.     }
  784.     /* First compute how many action points are available. */
  785.     /* Start with basic acp, normal or damaged as appropriate. */
  786.     if (unit->hp < u_hp_max(u)
  787.     && (dmgeffect = u_acp_damage_effect(u)) != lispnil) {
  788.     acp = damaged_acp(unit, dmgeffect);
  789.     } else {
  790.     acp = u_acp(u);
  791.     }
  792.     /* Adjust for occupants. */
  793.     for_all_occupants(unit, occ) {
  794.     if (is_active(occ)) {
  795.         acp = (acp * uu_acp_occ_effect(occ->type, u)) / 100;
  796.     }
  797.     }
  798.     /* Adjust for night time. */
  799.     if (night_at(unit->x, unit->y)) {
  800.         /* (should account for unit being on a road at night, etc) */
  801.     t = terrain_at(unit->x, unit->y);
  802.         acp = (acp * ut_acp_night_effect(u, t)) / 100;
  803.     }
  804.     /* (should) Adjust for season. */
  805.     if (u_acp_season_effect(u) != lispnil) {
  806.         acp = (acp * season_effect(u)) / 100;
  807.     }
  808.     /* Clip to upper and lower acp-per-turn limits. */
  809.     acp = max(acp, u_acp_turn_min(u));
  810.     if (u_acp_turn_max(u) >= 0)
  811.       acp = min(acp, u_acp_turn_max(u));
  812.     /* Increment the unit's available acp by the acp we get for this turn. */
  813.     unit->act->initacp = unit->act->acp + acp;
  814.     /* Now clip the unit's accumulated acp to its limits. */
  815.     minacp = u_acp_min(u);
  816.     maxacp = (u_acp_max(u) < 0 ? acp : u_acp_max(u));
  817.     unit->act->initacp = min(max(minacp, unit->act->initacp), maxacp);
  818.     /* Current acp is now the initial acp. */
  819.     unit->act->acp = unit->act->initacp;
  820.     unit->act->actualactions = unit->act->actualmoves = 0;
  821. }
  822.  
  823. /* Compute and return the acp of a damaged unit, using a list of (hp acp) pairs
  824.    and interpolating between them. */
  825.  
  826. int
  827. damaged_acp(unit, effect)
  828. Unit *unit;
  829. Obj *effect;
  830. {
  831.     int u = unit->type, hp = unit->hp, thishp, thisacp, nexthp, nextacp, rslt;
  832.     Obj *rest;
  833.  
  834.     for (rest = effect; rest != lispnil; rest = cdr(rest)) {
  835.     thishp = c_number(car(car(rest)));
  836.     thisacp = c_number(cadr(car(rest)));
  837.     if (cdr(rest)) {
  838.         nexthp = c_number(car(cadr(rest)));
  839.         nextacp = c_number(cadr(cadr(rest)));
  840.     } else {
  841.         nexthp = u_hp_max(u);
  842.         nextacp = u_acp(u);
  843.     }
  844.     if (unit->hp < thishp) {
  845.         /* Interpolate between thishp and 0. */
  846.         return (thisacp * hp) / thishp;
  847.     } else if (between(thishp, unit->hp, nexthp)) {
  848.         rslt = thisacp;
  849.         if (unit->hp != thishp) {
  850.         /* Add the linear interpolation. */
  851.             rslt += ((nextacp - thisacp) * (hp - thishp)) / (nexthp - thishp);
  852.         }
  853.         return rslt;
  854.     }
  855.     }
  856.     return u_acp(u);
  857. }
  858.  
  859. static void
  860. compute_season()
  861. {
  862.     Obj *names, *rest, *elt;
  863.  
  864.     curseasonname = NULL;
  865.     if (world.yearlength > 1) {
  866.     curyearpart = (g_turn() + g_initial_year_part()) % world.yearlength;
  867.     /* Determine the name of the season, if defined. */
  868.     names = g_season_names();
  869.     if (names != NULL && names != lispnil && consp(names)) {
  870.         for (rest = names; rest != lispnil; rest = cdr(rest)) {
  871.         elt = car(rest);
  872.         if (consp(elt)
  873.             && numberp(car(elt))
  874.             && numberp(cadr(elt))
  875.             && between(c_number(car(elt)), curyearpart, c_number(cadr(elt)))
  876.             && stringp(car(cddr(elt))))
  877.           curseasonname = c_string(car(cddr(elt)));
  878.         }
  879.     }
  880.     } else {
  881.     curyearpart = 0;
  882.     }
  883. }
  884.  
  885. static int
  886. season_effect(u)
  887. int u;
  888. {
  889.     int rslt = 100, thisyearpart, thiseffect, nextyearpart, nexteffect;
  890.     Obj *effects, *rest;
  891.  
  892.     if (curyearpart < 0)
  893.       compute_season();
  894.     effects = u_acp_season_effect(u);
  895.     for (rest = effects; rest != lispnil; rest = cdr(rest)) {
  896.         if (!numberp(car(car(rest))))
  897.           run_warning("not a number");
  898.     thisyearpart = c_number(car (car(rest)));
  899.         if (!numberp(cadr(car(rest))))
  900.           run_warning("not a number");
  901.     thiseffect = c_number(cadr(car(rest)));
  902.     if (cdr(rest)) {
  903.         nextyearpart = c_number(car (cadr(rest)));
  904.         nexteffect = c_number(cadr(cadr(rest)));
  905.     } else {
  906.         /* Cycles around to the beginning of the list. */
  907.         nextyearpart = c_number(car(car(effects))) + world.yearlength;
  908.         nexteffect = c_number(cadr(car(effects)));
  909.     }
  910.     if (between(thisyearpart, curyearpart, nextyearpart)) {
  911.         rslt = thiseffect;
  912.         if (curyearpart != thisyearpart) {
  913.         /* Add the linear interpolation. */
  914.             rslt += ((nexteffect - thiseffect) * (curyearpart - thisyearpart))
  915.                      / (nextyearpart - thisyearpart);
  916.         }
  917.         return rslt;
  918.     }
  919.     }
  920.     return rslt;
  921. }
  922.  
  923. /* Do some number of actions. */
  924.  
  925. static int
  926. move_some_units(lim)
  927. int lim;
  928. {
  929.     int num = 0, foundanytomove, curactor, numdelayed;
  930.     Unit *unit;
  931.  
  932.     /* Negative limits are effectively infinite. */
  933.     if (lim < 0)
  934.       lim = 100000000;
  935.   tryagain:
  936.     foundanytomove = FALSE;
  937.     numdelayed = 0;
  938.     for (curactor = 0; curactor < actionvector->numunits; ++curactor) {
  939.     unit = (actionvector->units)[curactor].unit;
  940.     if (unit->plan && unit->plan->delayed) {
  941.         ++numdelayed;
  942.         continue;
  943.     }
  944.     /* If the unit is keeping formation, then give it a chance to
  945.        adjust its position. */
  946.     if (is_active(unit)
  947.         && (unit->side ?
  948.         (unit->side->ingame && !unit->side->finishedturn) : TRUE)
  949.         && (unit->act && unit->act->acp > 0)
  950.         && (unit->plan && unit->plan->formation)) {
  951.         num += move_one_unit_multiple(unit, lim - num);
  952.         foundanytomove = TRUE;
  953.     }
  954.     if (unit_still_acting(unit, TRUE)) {
  955.         num += move_one_unit_multiple(unit, lim - num);
  956.         foundanytomove = TRUE;
  957.     }
  958.     if (unit_still_acting(unit, FALSE)) {
  959.         foundanytomove = TRUE;
  960.     }
  961.     if (num >= lim) 
  962.       return num;
  963.     }
  964.     if (!foundanytomove && numdelayed > 0) {
  965.     for (curactor = 0; curactor < actionvector->numunits; ++curactor) {
  966.         unit = (actionvector->units)[curactor].unit;
  967.         if (unit->plan)
  968.           unit->plan->delayed = FALSE;
  969.     }
  970.     goto tryagain;
  971.     }
  972.     if (!foundanytomove) {
  973.         if (g_use_side_priority() && curpriority < 2 * numsides) {
  974.         ++curpriority;
  975.         compose_actionvector();
  976.         goto tryagain;
  977.     }
  978.     }
  979.     return num;
  980. }
  981.  
  982. static int
  983. unit_still_acting(unit, checkwaiting)
  984. Unit *unit;
  985. int checkwaiting;
  986. {
  987.     return (is_active(unit)
  988.         && (unit->side
  989.         && unit->side->ingame
  990.         && !unit->side->finishedturn)
  991.         && (unit->act
  992.         && unit->act->acp > 0)
  993.         && ((unit->plan
  994.         && !unit->plan->asleep
  995.         && !unit->plan->reserve
  996.         && (checkwaiting ? !unit->plan->waitingfortasks : TRUE))
  997.         || has_pending_action(unit)));
  998. }
  999.  
  1000. /* Do a single unit's actions, up to the given limit or until it runs
  1001.    out of things it wants to do (or something happens to it). */
  1002.  
  1003. static int
  1004. move_one_unit_multiple(unit, lim)
  1005. Unit *unit;
  1006. int lim;
  1007. {
  1008.     int num = 0, buzz = 0, acp1;
  1009.     int rslt;
  1010.  
  1011.     if (unit->act == NULL || unit->act->initacp < 1)
  1012.       return 0;
  1013.     acp1 = unit->act->acp;
  1014.     while (is_active(unit)
  1015.        && (unit->act
  1016.            && unit->act->acp > u_acp_min(unit->type))
  1017.        && ((unit->plan
  1018.         && !unit->plan->asleep
  1019.         && !unit->plan->reserve
  1020.         && !unit->plan->delayed)
  1021.            || has_pending_action(unit))
  1022.        && num < lim
  1023.        && buzz < lim) {
  1024.     if (has_pending_action(unit)) {
  1025.         /* Execute the action directly. */
  1026.         rslt = execute_action(unit, &(unit->act->nextaction));
  1027.         /* Clear the action.  Note that the unit might have changed
  1028.            to a non-acting type, so we have to check for act struct. */
  1029.         if (unit->act)
  1030.           unit->act->nextaction.type = A_NONE;
  1031.         /* In any case, the game state is irrevocably altered. */
  1032.         gamestatesafe = FALSE;
  1033.         ++num;
  1034.     } else if (unit->plan) {
  1035.         if (unit->plan->formation && move_into_formation(unit)) {
  1036.         execute_plan(unit, 1);
  1037.         gamestatesafe = FALSE;
  1038.         ++buzz;
  1039.         }
  1040.         if (unit->plan->waitingfortasks
  1041.         || unit->plan->asleep
  1042.         || unit->plan->reserve
  1043.         || unit->plan->delayed)
  1044.           break;
  1045.         execute_plan(unit, 1);
  1046.         gamestatesafe = FALSE;
  1047.         ++buzz;
  1048.     } else {
  1049.         run_warning("Planless \"%s\" was asked to act", unit_desig(unit));
  1050.         ++buzz;
  1051.     }
  1052.     /* This should never happen? */
  1053.     if (unit->act && unit->act->acp == acp1 && num > 1) {
  1054.         /* Blast the action. */
  1055.         unit->act->nextaction.type = A_NONE;
  1056.         /* Blast the plan. */
  1057.         if (unit->plan)
  1058.           unit->plan->type = PLAN_NONE;
  1059.         if (unit->plan && probability(5))
  1060.           unit->plan->asleep = TRUE;
  1061.         Dprintf("%s was confused, starting over\n", unit_desig(unit));
  1062.     }
  1063.     }
  1064.     return num;
  1065. }
  1066.  
  1067. /* This explicitly finishes out a side's activity for the turn. */
  1068.  
  1069. void
  1070. finish_turn(side)
  1071. Side *side;
  1072. {
  1073.     Side *side2;
  1074.  
  1075.     /* Flag the side as being done for this turn. */
  1076.     side->finishedturn = TRUE;
  1077.     /* Stop counting down our time consumption. */
  1078.     side->totaltimeused += (time(0) - side->turnstarttime);
  1079.     /* Clue everybody in. */
  1080.     for_all_sides(side2) {
  1081.     update_side_display(side2, side, TRUE);
  1082.     }
  1083.     Dprintf("%s finished its turn.\n", side_desig(side));
  1084. }
  1085.  
  1086. /* Take care of details that no longer require any interaction, at least
  1087.    none that can't wait until the next turn. */
  1088.  
  1089. static void
  1090. finish_movement()
  1091. {
  1092.     int lostacp;
  1093.     Unit *unit;
  1094.     Side *side, *side2;
  1095.  
  1096.     for_all_sides (side) {
  1097.     /* Remove dead units that have been dead more than a turn. (?) */
  1098.     flush_side_dead(side);
  1099.     if (Debug) {
  1100.         lostacp = 0;
  1101.         for_all_side_units(side, unit) {
  1102.         if (is_active(unit) && unit->act && unit->act->acp > 0) {
  1103.             lostacp += unit->act->acp;
  1104.         }
  1105.         }
  1106.         if (lostacp > 0) {
  1107.         Dprintf("%s forfeited %d acp overall.\n",
  1108.             side_desig(side), lostacp);
  1109.         }
  1110.     }
  1111.     if (side_has_ai(side)) {
  1112.         ai_finish_movement(side);
  1113.     }
  1114.     }
  1115.     for_all_sides(side)  {
  1116.     for_all_sides(side2) {
  1117.         update_side_display(side, side2, TRUE);
  1118.     }
  1119.     }
  1120. }
  1121.  
  1122. /* See how any agreements' terms are holding up. */
  1123.  
  1124. static void
  1125. test_agreements()
  1126. {
  1127.     Agreement *ag;
  1128.     Side *side;
  1129.     Unit *unit;
  1130.  
  1131.     for_all_agreements(ag) {
  1132.     if (ag->state == in_force) {
  1133.         /* what? */
  1134.     }
  1135.     }
  1136. }
  1137.  
  1138. /* Compute sun-related data. */
  1139.  
  1140. static void
  1141. compute_sun()
  1142. {
  1143.     int curtime;
  1144.  
  1145.     switch (world.daylength) {
  1146.       case 0:
  1147.     /* Sun is at a fixed position. */
  1148.     daynight = TRUE;
  1149.     /* (should be possible to set explicitly somehow? implicitly from lat/long?) */
  1150.     sunx = area.width / 2;  suny = area.height / 2;
  1151.     break;
  1152.       case 1:
  1153.     /* No sun effects at all, every place uniformly lit. */
  1154.           daynight = FALSE;
  1155.     break;
  1156.       default:
  1157.     /* Normal days and nights. */
  1158.     daynight = TRUE;
  1159.     /* If world has a appropriate circumference, the sun moves over
  1160.        it at a regular pace. */
  1161.     if (world.circumference >= area.width) {
  1162.         lastsunx = sunx;  lastsuny = suny;
  1163.         curtime = (g_turn() + g_initial_day_part()) % world.daylength;
  1164.         sunx = (curtime * world.circumference) / world.daylength + area.width / 2;
  1165.         /* (should adjust suny for nonzero latitudes and axial tilt) */
  1166.         suny = area.height / 2;
  1167.     }
  1168.     break;
  1169.     }
  1170.     if (daynight) {
  1171.     Dprintf("Sun is now at %d,%d\n", sunx, suny);
  1172.     }
  1173. }
  1174. /* Compute the position of the sun for this turn. */
  1175.  
  1176. static void
  1177. run_sun()
  1178. {
  1179.     int x, y;
  1180.     Side *side;
  1181.  
  1182.     compute_sun();
  1183.     if (world.daylength > 1 && world.circumference >= area.width) {
  1184.     /* Update the appearance of any cells whose lighting has changed. */
  1185.     for_all_cells(x, y) {
  1186.         if (lighting(x, y, sunx, suny) != lighting(x, y, lastsunx, lastsuny)) {
  1187.         for_all_sides(side) {
  1188.             update_cell_display(side, x, y, FALSE);
  1189.             }
  1190.         }
  1191.     }
  1192.     }
  1193. }
  1194.  
  1195. /* Seasonal change moves the average temperature up and down gradually,
  1196.    modifying it according to the terrain underneath. */
  1197.  
  1198. /* This should check that equator and northpole are not equal. */
  1199.  
  1200. static void
  1201. run_environment()
  1202. {
  1203.     int yrlen = world.yearlength;
  1204.     int season, x, y, dir, t, lattemp, celltemp;
  1205.     int u, temp, comfmin, comfmax, range;
  1206.     Unit *unit;
  1207.     Side *side;
  1208.  
  1209.     if (mintemp == maxtemp && !any_wind_variation_in_layer)
  1210.       return;
  1211.     if (!temperatures_defined()) {
  1212.         allocate_area_temperatures();
  1213.         allocate_area_scratch(2);
  1214.     }
  1215. #if 0
  1216.     float spoletemp, npoletemp, equatortemp;
  1217.     float poledelta, equatordelta, ntempdelta, stempdelta;
  1218.  
  1219.     if (yrlen > 1 /* and axial tilt... */) {
  1220.     /* Compute the difference between summer and winter temps. */
  1221.     /* (Should be precomputed.) */
  1222.     poledelta = (g_summer_pole() - g_winter_pole()) / (yrlen / 2);
  1223.     equatordelta = (g_summer_equator() - g_winter_equator()) / (yrlen / 2);
  1224.     /* Compute where we are in the cycle of seasons. */
  1225.     /* Compute temps at poles and equator. */
  1226.     if (curyearpart <= yrlen / 2) {
  1227.         npoletemp = g_winter_pole() + curyearpart * poledelta;
  1228.         equatortemp = g_winter_equator() + curyearpart * equatordelta;
  1229.         spoletemp = g_winter_pole() + (yrlen/2 - curyearpart) * poledelta;
  1230.     } else {
  1231.         npoletemp = g_winter_pole() + (yrlen - curyearpart) * poledelta;
  1232.         equatortemp = g_winter_equator() + (yrlen - curyearpart) * equatordelta;
  1233.         spoletemp = g_winter_pole() + (curyearpart - yrlen/2) * poledelta;
  1234.     }
  1235.     Dprintf("Temps N %f Eq %f S %f\n", npoletemp, equatortemp, spoletemp);
  1236.     /* Compute the temperature variation from one lat to the next. */
  1237.     ntempdelta = (equatortemp-npoletemp)/(world.northpole-world.equator);
  1238.     stempdelta = (equatortemp-spoletemp)/(world.equator-world.southpole);
  1239.     }
  1240. #endif
  1241.     /* Compute the average temperature at each point in the world. */
  1242.     for (y = area.height-1; y >= 0; --y) {
  1243.     for (x = 0; x < area.width; ++x) {
  1244.         if (!in_area(x, y)) continue;
  1245.         /* Save the prev temp. */
  1246.         set_tmp1_at(x, y, temperature_at(x, y));
  1247.         t = terrain_at(x, y);
  1248.         celltemp = t_temp_avg(t);
  1249.         /* (should account for latitude/season effect here somehow) */
  1250.         /* Add in a random variation if specified. */
  1251.         if (t_temp_variability(t) > 0) {
  1252.         celltemp += (xrandom(t_temp_variability(t))
  1253.                 - t_temp_variability(t)/2);
  1254.         }
  1255.         /* Higher elevations can be much colder. */
  1256.         /* (In this pos, will influence lowlands via moderation - realistic?) */
  1257.         if (elevations_defined()
  1258.             && g_temp_floor_elev() != 0
  1259.             && elev_at(x, y) < g_temp_floor_elev()) {
  1260.         celltemp -=
  1261.             ((celltemp - g_temp_floor()) * elev_at(x, y))
  1262.             / g_temp_floor_elev();
  1263.         }
  1264.         /* Record the (unmoderated) temperature of the cell. */
  1265.         set_temperature_at(x, y, celltemp);
  1266.     }
  1267.     }
  1268.     /* Sometimes the scale of the world is such that neighboring cells
  1269.        influence each other's temperatures. */
  1270.     if (g_temp_mod_range() > 0) {
  1271.     /* only doing a range of 1... */
  1272.     for_all_interior_cells(x, y) {
  1273.         set_tmp2_at(x, y, temperature_at(x, y));
  1274.         for_all_directions(dir) {
  1275.         set_tmp2_at(x, y,
  1276.                 (tmp2_at(x, y)
  1277.                  + temperature_at(x+dirx[dir], y+diry[dir])));
  1278.         }
  1279.     }
  1280.     for_all_interior_cells(x, y) {
  1281.         set_temperature_at(x, y, (tmp2_at(x, y) / (NUMDIRS + 1)));
  1282.     }
  1283.     }
  1284.     /* See if any displays should change and report if so. */
  1285.     for_all_sides(side) {
  1286.     if (side_has_display(side)) {
  1287.             for_all_cells(x, y) {
  1288.             if (temperature_at(x, y) != tmp1_at(x, y) &&
  1289.                 (g_see_all() || terrain_view(side, x, y) != UNSEEN)) {
  1290.             update_cell_display(side, x, y, 34);
  1291.         }
  1292.         }
  1293.         flush_display_buffers(side);
  1294.     }
  1295.     }
  1296.     /* Affect any temperature-sensitive units. */
  1297.     for_all_units(unit) {
  1298.     if (in_play(unit) &&
  1299.         !(unit->transport != NULL &&
  1300.           uu_temp_protect(unit->transport->type, unit->type))) {
  1301.         u = unit->type;
  1302.         temp = temperature_at(unit->x, unit->y);
  1303. #if 0
  1304.         if (between(u_survival_min(u), temp, u_survival_max(u))) {
  1305.         if (temp < (comfmin = u_comfort_min(u))) {
  1306.             range = comfmin - u_survival_min(u);
  1307.             if (probability((100 * (comfmin - temp)) / range)) {
  1308.             damage_unit_with_temperature(unit, 1);
  1309.             }
  1310.         } else if (temp > (comfmax = u_comfort_max(u))) {
  1311.             range = u_survival_max(u) - comfmax;
  1312.             if (probability((100 * (temp - comfmax)) / range)) {
  1313.             damage_unit_with_temperature(unit, 1);
  1314.             }
  1315.         } else {
  1316.             /* Unit gets off scot-free - this time... */
  1317.         }
  1318.         } else {
  1319.         damage_unit_with_temperature(unit, unit->hp);
  1320.         }
  1321. #endif
  1322.     }
  1323.     }
  1324.     /* Do wind changes. */
  1325.     if (any_wind_variation_in_layer) {
  1326.     for_all_interior_cells(x, y) {
  1327.         set_tmp1_at(x, y, raw_wind_at(x, y));
  1328.     }
  1329.     for_all_interior_cells(x, y) {
  1330.         int winddir = wind_dir_at(x, y);
  1331.         int windforce = wind_force_at(x, y);
  1332.         int t = terrain_at(x, y);
  1333.         int anychange;
  1334.  
  1335.         anychange = FALSE;
  1336.         if (probability(t_wind_variability(t))) {
  1337.         winddir = (flip_coin() ? right_dir(winddir) : left_dir(winddir));
  1338.         anychange = TRUE;
  1339.         }
  1340.         if (probability(t_wind_force_variability(t))) {    
  1341.         windforce += (flip_coin() ? 1 : -1);
  1342.         windforce = max(windforce, t_wind_force_min(t));
  1343.         windforce = min(windforce, t_wind_force_max(t));
  1344.         anychange = TRUE;
  1345.         }
  1346.         if (anychange)
  1347.           set_wind_at(x, y, winddir, windforce);
  1348.     }
  1349.     /* See if any displays should change and report if so. */
  1350.     for_all_sides(side) {
  1351.         if (side_has_display(side)) {
  1352.         for_all_cells(x, y) {
  1353.             if (raw_wind_at(x, y) != tmp1_at(x, y)
  1354.             && (g_see_all() || terrain_view(side, x, y) != UNSEEN)) {
  1355.             update_cell_display(side, x, y, 35);
  1356.             }
  1357.         }
  1358.         flush_display_buffers(side);
  1359.         }
  1360.     }
  1361.     }
  1362. }
  1363.  
  1364. static void
  1365. damage_unit_with_temperature(unit, n)
  1366. Unit *unit;
  1367. int n;
  1368. {
  1369.     if (n >= unit->hp) {
  1370.     Dprintf("%s dies from excessive temps\n", unit_desig(unit));
  1371.     kill_unit(unit, H_UNIT_KILLED);
  1372.     } else {
  1373.     Dprintf("%s damaged by excessive temps\n", unit_desig(unit));
  1374.     unit->hp -= n;
  1375.     }
  1376. }
  1377.  
  1378. static void
  1379. mix_winds()
  1380. {
  1381. }
  1382.  
  1383. /* Given that the spying unit is going to get info about other units at this
  1384.    location, figure out just what it is going to see. */
  1385.  
  1386. static void
  1387. spy_on_location(x, y)
  1388. int x, y;
  1389. {
  1390.     int qual;
  1391.     Unit *unit2, *occ;
  1392.  
  1393.     for_all_stack(x, y, unit2) {
  1394.         if (unit2->side != tmpunit->side) {
  1395.             qual = uu_spy_quality(tmpunit->type, unit2->type);
  1396.             if (probability(qual)) {
  1397.                 /* Spy got something, report it. */
  1398.                 /* (should be more worked-out, dunno exactly how) */
  1399.                 see_exact(tmpunit->side, x, y);
  1400.                 for_all_occupants(unit2, occ) {
  1401.                     /* (should get info about occupants) */
  1402.                 }
  1403.             }
  1404.         }
  1405.     }
  1406. }
  1407.  
  1408. /* Certain kinds of units can do spying for the side they're on. */
  1409. /* (should reindent) */
  1410. static void
  1411. run_spies()
  1412. {
  1413.     int chance;
  1414.     Unit *unit;
  1415.  
  1416.     if (any_spying < 0) {
  1417.     int u;
  1418.  
  1419.     any_spying = FALSE;
  1420.     for_all_unit_types(u) {
  1421.         if (u_spy_chance(u) > 0) {
  1422.         any_spying = TRUE;
  1423.         break;
  1424.         }
  1425.     }
  1426.     if (g_see_all())
  1427.       any_spying = FALSE;  /* override */
  1428.     }
  1429.     if (!any_spying)
  1430.       return;
  1431.     Dprintf("Running spies\n");
  1432.     for_all_units(unit) {
  1433.     if (is_active(unit)) {
  1434.         chance = u_spy_chance(unit->type);
  1435.         if (chance > 0) {
  1436.             if (xrandom(10000) < chance) {
  1437.             /* Spying is successful, decide how much was seen. */
  1438.             tmpunit = unit;
  1439.             apply_to_area(unit->x, unit->y, u_spy_range(unit->type),
  1440.                       spy_on_location);
  1441.             }
  1442.         }
  1443.     }
  1444.     }
  1445. }
  1446.  
  1447. /* Figure out ahead of time which random event methods to run. */
  1448.  
  1449. void
  1450. init_random_events()
  1451. {
  1452.     int i, k;
  1453.     Obj *randomeventlist, *rest, *evttype;
  1454.  
  1455.     numrandomevents = 0;
  1456.     randomeventlist = g_random_events();
  1457.     if (randomeventlist == NULL || randomeventlist == lispnil)
  1458.       return;
  1459.     for (rest = randomeventlist; rest != lispnil; rest = cdr(rest)) {
  1460.     evttype = car(rest);
  1461.     if (symbolp(evttype)) {
  1462.         k = keyword_code(c_string(evttype));
  1463.         for (i = 0; randomeventmethods[i].key != 0; ++i) {
  1464.         if (k == randomeventmethods[i].key
  1465.             && randomeventmethods[i].fn != NULL
  1466.             && (randomeventmethods[i].initfn == NULL
  1467.             || (*(randomeventmethods[i].initfn))())) {
  1468.             randomeventindices[numrandomevents++] = i;
  1469.         }
  1470.         }
  1471.     }
  1472.     }
  1473. }
  1474.  
  1475. /* Run the current cache of random event methods. */
  1476.  
  1477. static void
  1478. run_random_events()
  1479. {
  1480.     int i;
  1481.  
  1482.     if (numrandomevents > 0) {
  1483.     Dprintf("Running random events\n");
  1484.     for (i = 0; i < numrandomevents; ++i) {
  1485.         (*(randomeventmethods[randomeventindices[i]].fn))();
  1486.     }
  1487.     }
  1488. }
  1489.  
  1490. /* Test whether accidents can happen in this game. */
  1491.  
  1492. static int
  1493. init_accidents()
  1494. {
  1495.     int u, t;
  1496.     
  1497.     for_all_unit_types(u) {
  1498.         for_all_terrain_types(t) {
  1499.             if (ut_accident_vanish(u, t) > 0
  1500.         || ut_accident_hit(u, t) > 0)
  1501.           return TRUE;
  1502.         }
  1503.     }
  1504.     return FALSE;
  1505. }
  1506.  
  1507. /* Test each unit that is out in the open to see if a terrain-related
  1508.    accident happens to it.  Accidents can either kill the unit instantly or
  1509.    just damage it. */
  1510.  
  1511. static void
  1512. run_accidents()
  1513. {
  1514.     int t;
  1515.     Unit *unit;
  1516.  
  1517.     for_all_units(unit) {
  1518.     if (in_play(unit) && unit->transport == NULL) {
  1519.         t = terrain_at(unit->x, unit->y);
  1520.         if (xrandom(10000) < ut_accident_vanish(unit->type, t)) {
  1521.             /* Kill the unit outright. */
  1522.         kill_unit(unit, H_UNIT_VANISHED);
  1523.         /* should make a hevt */
  1524.         } else if (xrandom(10000) < ut_accident_hit(unit->type, t)) {
  1525.         /* Damage the unit. */
  1526.         unit->hp2 -= ut_accident_damage(unit->type, t);
  1527.         /* (should be able to pass reason to damage_unit) */
  1528.         damage_unit(unit);
  1529.         }
  1530.     }
  1531.     }
  1532. }
  1533.  
  1534. /* Test whether attrition can ever happen in this game. */
  1535.  
  1536. static int
  1537. init_attrition()
  1538. {
  1539.     int u, t;
  1540.     
  1541.     for_all_unit_types(u) {
  1542.         for_all_terrain_types(t) {
  1543.             if (ut_attrition(u, t) > 0)
  1544.           return TRUE;
  1545.         }
  1546.     }
  1547.     return FALSE;
  1548. }
  1549.  
  1550. /* Attrition only takes out a few hp at a time, but can be deadly... */
  1551.  
  1552. static void
  1553. run_attrition()
  1554. {
  1555.     int u, dmg;
  1556.     Unit *unit;
  1557.  
  1558.     for_all_units(unit) {
  1559.     if (in_play(unit)) {
  1560.         u = unit->type;
  1561.         dmg = prob_fraction(ut_attrition(u, terrain_at(unit->x, unit->y)));
  1562.         /* This is like hit_unit but doesn't have other effects. */
  1563.         unit->hp2 -= dmg;
  1564.         /* (should be able to pass reason to damage_unit) */
  1565.         damage_unit(unit);
  1566.     }
  1567.     }
  1568. }
  1569.  
  1570. /* Test whether revolts can ever happen in this game. */
  1571.  
  1572. static int
  1573. init_revolts()
  1574. {
  1575.     int u;
  1576.  
  1577.     for_all_unit_types(u) {
  1578.     if (u_revolt(u) > 0)
  1579.       return TRUE;
  1580.     }
  1581.     return FALSE;
  1582. }
  1583.  
  1584. /* Check each unit to see whether it revolts spontaneously.  While
  1585.    surrender is influenced by nearby units, revolt takes only the
  1586.    overall state of the world into account. */
  1587.  
  1588. static void
  1589. run_revolts()
  1590. {
  1591.     Unit *unit;
  1592.  
  1593.     for_all_units(unit) {
  1594.     if (in_play(unit) && u_revolt(unit->type) > 0) {
  1595.         unit_revolt(unit);
  1596.     }
  1597.     }
  1598. }
  1599.  
  1600. static void
  1601. unit_revolt(unit)
  1602. Unit *unit;
  1603. {
  1604.     int u = unit->type, ux = unit->x, uy = unit->y, chance, count;
  1605.     Side *oldside = unit->side, *newside;
  1606.  
  1607.     chance = u_revolt(u);
  1608.     if (0 /* affected by politics */) {
  1609.     }
  1610.     if (xrandom(10000) < chance) {
  1611.     if (0 /* leanings towards various sides */) {
  1612.         /* (should want to change to best-liked side) */
  1613.     } else {
  1614.         count = 0;
  1615.         while (count++ < 200) {
  1616.         newside = side_n(xrandom(numsides + 1));
  1617.         if (unit_allowed_on_side(unit, newside)
  1618.             && newside != oldside) {
  1619.             break;
  1620.         }
  1621.         }
  1622.     }
  1623.     /* Might not have been much of a revolt. :-) */
  1624.     if (newside == oldside)
  1625.       return;
  1626.     unit_changes_side(unit, newside, H_UNIT_ACQUIRED, 0 /* H_UNIT_REVOLTED */);
  1627.     see_exact(oldside, ux, uy);
  1628.     update_cell_display(oldside, ux, uy, TRUE);
  1629.     all_see_cell(ux, uy);
  1630.     }
  1631. }
  1632.  
  1633. /* Test whether surrenders can happen in this game. */
  1634.  
  1635. int *surrender_ranges;
  1636.  
  1637. static int
  1638. init_surrenders()
  1639. {
  1640.     int u1, u2, u3, range, rslt = FALSE;
  1641.     
  1642.     for_all_unit_types(u1) {
  1643.         for_all_unit_types(u2) {
  1644.             if (uu_surrender_chance(u1, u2) > 0) {
  1645.         rslt = TRUE;
  1646.         if (surrender_ranges == NULL)
  1647.           surrender_ranges = (int *) xmalloc(MAXUTYPES * sizeof(int));
  1648.         for_all_unit_types(u3) surrender_ranges[u3] = -1;
  1649.         range = uu_surrender_range(u1, u2);
  1650.         surrender_ranges[u1] = max(range, surrender_ranges[u1]);
  1651.             }
  1652.         }
  1653.     }
  1654.     return rslt;
  1655. }
  1656.  
  1657. static void
  1658. run_surrenders()
  1659. {
  1660.     Unit *unit;
  1661.  
  1662.     for_all_units(unit) {
  1663.     if (in_play(unit)) {
  1664.         unit_surrender(unit);
  1665.     }
  1666.     }
  1667. }
  1668.  
  1669. /* Units may surrender to enemy units that are visible nearby.
  1670.    Independents have to be treated specially, since they don't have a view
  1671.    to work from.  We sort of compute the view "on the fly". */
  1672.  
  1673. static void
  1674. unit_surrender(unit)
  1675. Unit *unit;
  1676. {
  1677.     int u = unit->type, dir, x1, y1, range, surrounded = TRUE;
  1678.     Unit *unit2;
  1679.  
  1680.     range = surrender_ranges[u];
  1681.     if (range < 0) {
  1682.     /* This unit won't surrender, nothing to do. */
  1683.     } else if (range > 1) {
  1684.     /* (should write general case) */
  1685.     } else {
  1686.     /* Range is 0 or 1; check other units in this cell. */
  1687.     for_all_stack(unit->x, unit->y, unit2) {
  1688.         if (in_play(unit2)
  1689.         && unit2->side != unit->side
  1690.         && uu_surrender_chance(u, unit2->type) > 0
  1691.         && visible_to(unit, unit2)) {
  1692.         maybe_surrender_to(unit, unit2);
  1693.         }
  1694.     }
  1695.     /* Check on adjacent units. */
  1696.         if (range == 1) {
  1697.       for_all_directions(dir) {
  1698.         if (interior_point_in_dir(unit->x, unit->y, dir, &x1, &y1)) {
  1699.         for_all_stack(unit->x, unit->y, unit2) {
  1700.             if (in_play(unit2)
  1701.             && unit2->side != unit->side
  1702.             && uu_surrender_chance(u, unit2->type) > 0
  1703.             && visible_to(unit, unit2)) {
  1704.             maybe_surrender_to(unit, unit2);
  1705.             }
  1706.         }
  1707.         }
  1708.       }
  1709.     }
  1710.     }
  1711. }
  1712.  
  1713. /* Calculate whether one unit is visible to another, even if the other is independent. */
  1714.  
  1715. int
  1716. visible_to(unit, unit2)
  1717. Unit *unit, *unit2;
  1718. {
  1719.     int uview;
  1720.  
  1721.     if (g_see_all()) {
  1722.     return TRUE;
  1723.     } else if (unit->side != NULL) {
  1724.         uview = unit_view(unit->side, unit2->x, unit2->y);
  1725.     return (uview != EMPTY && vtype(uview) == unit2->type);
  1726.     } else {
  1727.     /* (should be more careful to check see-chances) */
  1728.         if (distance(unit->x, unit->y, unit2->x, unit2->y) <= u_vision_range(unit->type))
  1729.           return TRUE;
  1730.         else
  1731.           return FALSE;
  1732.     }
  1733. }
  1734.  
  1735. static void
  1736. maybe_surrender_to(unit, unit2)
  1737. Unit *unit, *unit2;
  1738. {
  1739.     int chance;
  1740.  
  1741.     chance = uu_surrender_chance(unit->type, unit2->type);
  1742.     if (xrandom(10000) < chance) {
  1743.     /* (not really correct) */
  1744.     set_unit_side(unit, unit2->side);
  1745.     }
  1746. }
  1747.  
  1748. int tmpexcess;
  1749.  
  1750. /* We've "found what we were searching for" when the excess to distribute
  1751.    is gone. */
  1752.  
  1753. static int
  1754. excess_left(x, y)
  1755. int x, y;
  1756. {
  1757.     return (tmpexcess > 0);
  1758. }
  1759.  
  1760. static void
  1761. try_transfer_to_cell(x, y)
  1762. int x, y;
  1763. {
  1764.     Unit *unit2, *occ;
  1765.  
  1766.     if (tmpexcess <= 0)
  1767.       return;
  1768.     for_all_stack(x, y, unit2) {
  1769.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  1770.         try_transfer(tmpunit, unit2, tmpmtype);
  1771.     }
  1772.     }
  1773.     for_all_stack(x, y, unit2) {
  1774.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  1775.         for_all_occupants(unit2, occ) {
  1776.         if (in_play(occ) && occ->side == tmpunit->side) {
  1777.             try_transfer(tmpunit, occ, tmpmtype);
  1778.         }
  1779.         }
  1780.     }
  1781.     }
  1782. }
  1783.  
  1784. static int
  1785. sharable_left(x, y)
  1786. int x, y;
  1787. {
  1788.     return tmpunit->supply[tmpmtype] > (um_storage_x(tmpunit->type, tmpmtype) / 2);
  1789. }
  1790.  
  1791. static void
  1792. try_sharing_with_cell(x, y)
  1793. int x, y;
  1794. {
  1795.     Unit *unit2, *occ;
  1796.  
  1797.     if (!sharable_left(x, y))
  1798.       return;
  1799.     for_all_stack(x, y, unit2) {
  1800.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  1801.         try_sharing(tmpunit, unit2, tmpmtype);
  1802.     }
  1803.     }
  1804.     for_all_stack(x, y, unit2) {
  1805.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  1806.         for_all_occupants(unit2, occ) {
  1807.         if (in_play(occ) && occ->side == tmpunit->side) {
  1808.             try_sharing(tmpunit, occ, tmpmtype);
  1809.         }
  1810.         }
  1811.     }
  1812.     }
  1813. }
  1814.  
  1815. /* The main routine does production, distribution, and discarding in order. */
  1816.  
  1817. static void
  1818. run_economy()
  1819. {
  1820.     int u, m, t, amt, dist, x, y, x1, y1, m1, m2;
  1821.     int prod, ptivity, stor, oldamt, newamt;
  1822.     int ttotals[MAXMTYPES], utotals[MAXMTYPES];
  1823.     Unit *unit;
  1824.     
  1825.     if (nummtypes == 0)
  1826.       return;
  1827.     if (any_unit_production < 0) {
  1828.     any_unit_production = FALSE;
  1829.     for_all_unit_types(u) {
  1830.         for_all_material_types(m) {
  1831.         if (max(um_base_production(u, m),
  1832.             um_occ_production(u, m)) > 0) {
  1833.             any_unit_production = TRUE;
  1834.             break;
  1835.         }
  1836.         }
  1837.     }
  1838.     }
  1839.     if (any_terrain_production < 0) {
  1840.     any_terrain_production = FALSE;
  1841.     for_all_terrain_types(t) {
  1842.         for_all_material_types(m) {
  1843.         if (tm_production(t, m) > 0) {
  1844.             any_terrain_production = TRUE;
  1845.             break;
  1846.         }
  1847.         }
  1848.     }
  1849.     }
  1850.     if (any_people_production < 0) {
  1851.     any_people_production = FALSE;
  1852.     for_all_material_types(m1) {
  1853.         if (m_people(m1) > 0) {
  1854.         for_all_material_types(m2) {
  1855.             if (mm_people_production(m1, m2) > 0) {
  1856.             any_people_production = TRUE;
  1857.             break;
  1858.             }
  1859.         }
  1860.         }
  1861.     }
  1862.     }
  1863.     if (!any_unit_production
  1864.     && !any_terrain_production
  1865.     && !any_people_production)
  1866.       return;
  1867.     /* (should find other reasons not to run this) */
  1868.     Dprintf("Running economy\n");
  1869.     for_all_material_types(m)
  1870.       ttotals[m] = utotals[m] = 0;
  1871.     /* Make new materials but don't clip to storage capacities yet. */
  1872.     if ((any_terrain_production || any_people_production)
  1873.     && any_cell_materials_defined()) {
  1874.     for_all_material_types(m) {
  1875.         if (cell_material_defined(m)) {
  1876.         for_all_cells(x, y) {
  1877.             if (any_terrain_production) {
  1878.             t = terrain_at(x, y);
  1879.             prod = tm_production(t, m);
  1880.             if (prod > 0) {
  1881.                 oldamt = material_at(x, y, m);
  1882.                 newamt = oldamt + prod;
  1883.                 set_material_at(x, y, m, newamt);
  1884.                 if (Debug) {
  1885.                 stor = tm_storage_x(t, m);
  1886.                 if (newamt > stor)
  1887.                   ttotals[m] += (newamt - stor);
  1888.                 }
  1889.             }
  1890.             }
  1891.             if (any_people_production) {
  1892.             for_all_material_types(m1) {
  1893.                 if (m_people(m1) > 0) {
  1894.                 prod = mm_people_production(m1, m);
  1895.                 if (prod > 0) {
  1896.                     oldamt = material_at(x, y, m);
  1897.                     newamt = oldamt + prod;
  1898.                     set_material_at(x, y, m, newamt);
  1899.                     if (Debug) {
  1900.                     stor = tm_storage_x(t, m);
  1901.                     if (newamt > stor)
  1902.                       ttotals[m] += (newamt - stor);
  1903.                     }
  1904.                 }
  1905.                 }
  1906.             }
  1907.             }
  1908.         }
  1909.         }
  1910.     }
  1911.     }
  1912.     if (any_unit_production) {
  1913.     for_all_units(unit) {
  1914.         if (in_play(unit) && completed(unit)) {
  1915.         u = unit->type;
  1916.         for_all_material_types(m) {
  1917.             t = terrain_at(unit->x, unit->y);
  1918.             prod = base_production(unit, m);
  1919.             if (prod > 0) {
  1920.             ptivity = ut_productivity(u, t);
  1921.             /* Note that we've switched to hundredths. */
  1922.             ptivity = max(ptivity, um_productivity_min(u, m));
  1923.             ptivity = min(ptivity, um_productivity_max(u, m));
  1924.             amt = prob_fraction(prod * ptivity);
  1925.             unit->supply[m] += amt;
  1926.             if (Debug && unit->supply[m] > um_storage_x(u, m))
  1927.               utotals[m] += (unit->supply[m] - um_storage_x(u, m));
  1928.             }
  1929.         }
  1930.         }
  1931.     }
  1932.     }
  1933.     Dprintf("Overflow is:");
  1934.     Dprintf("  (for terrain)");
  1935.     for_all_material_types(m) Dprintf(" %d", ttotals[m]);
  1936.     Dprintf("  (for units)");
  1937.     for_all_material_types(m) Dprintf(" %d", utotals[m]);
  1938.     Dprintf("\n");
  1939.     /* Move stuff around - try to get rid of any excess. */
  1940.     /* (should also do cell-cell, cell-unit, unit-cell xfers) */
  1941.     for_all_units(unit) {
  1942.     if (in_play(unit) && !indep(unit)) {
  1943.         u = unit->type;
  1944.         for_all_material_types(m) {
  1945.         stor = um_storage_x(u, m);
  1946.         if (unit->supply[m] > stor) {
  1947.             dist = um_outlength(u, m);
  1948.             if (dist >= 0) {
  1949.                 tmpunit = unit;
  1950.                 tmpmtype = m;
  1951.                 tmpexcess = unit->supply[m] - stor;
  1952.             search_and_apply(unit->x, unit->y, dist, excess_left,
  1953.                      &x1, &y1, 1,
  1954.                      try_transfer_to_cell, 999999);
  1955.             }
  1956.         }
  1957.         }
  1958.     }
  1959.     }
  1960.     /* (should) Limit overall people density. */
  1961.     if (0 /* any people limits */) {
  1962.         int numpeople;
  1963.     
  1964.     for_all_cells(x, y) {
  1965.         numpeople = 0;
  1966.         for_all_material_types(m) {
  1967.         if (0 /* repns people */) {
  1968.             numpeople += m_people(m) * material_at(x, y, m);
  1969.             /* (should save in scratch layer) */
  1970.         }
  1971.         }
  1972.     }
  1973.     /* (should have excess people migrate to cells with room) */
  1974.     /* (eliminate any leftover) */
  1975.     }
  1976.     /* Throw away excess that can't be stored anywhere. */
  1977.     for_all_material_types(m)
  1978.       ttotals[m] = utotals[m] = 0;
  1979.     if (any_cell_materials_defined()) {
  1980.     for_all_material_types(m) {
  1981.         if (cell_material_defined(m)) {
  1982.         for_all_cells(x, y) {
  1983.             t = terrain_at(x, y);
  1984.             stor = tm_storage_x(t, m);
  1985.             oldamt = material_at(x, y, m);
  1986.             newamt = min(oldamt, stor);
  1987.             set_material_at(x, y, m, newamt);
  1988.             if (Debug && newamt < oldamt)
  1989.               ttotals[m] += (oldamt - newamt);
  1990.         }
  1991.         }
  1992.     }
  1993.     }
  1994.     for_all_units(unit) {
  1995.     u = unit->type;
  1996.     for_all_material_types(m) {
  1997.         stor = um_storage_x(u, m);
  1998.         oldamt = unit->supply[m];
  1999.         newamt = min(oldamt, stor);
  2000.         unit->supply[m] = newamt;
  2001.         if (Debug && newamt < oldamt)
  2002.           utotals[m] += (oldamt - newamt);
  2003.     }
  2004.     }
  2005.     Dprintf("Discarded ");
  2006.     Dprintf("  (for terrain)");
  2007.     for_all_material_types(m) Dprintf(" %d", ttotals[m]);
  2008.     Dprintf("  (for units)");
  2009.     for_all_material_types(m) Dprintf(" %d", utotals[m]);
  2010.     Dprintf("\n");
  2011.     /* This next phase is for sharing of scarcer supplies. */
  2012.     for_all_units(unit) {
  2013.     if (in_play(unit) && !indep(unit)) {
  2014.         u = unit->type;
  2015.         for_all_material_types(m) {
  2016.         dist = um_outlength(u, m);
  2017.         if (dist >= 0) {
  2018.             tmpunit = unit;
  2019.             tmpmtype = m;
  2020.             search_and_apply(unit->x, unit->y, dist, sharable_left,
  2021.                      &x1, &y1, 1,
  2022.                      try_sharing_with_cell, 999999);
  2023.         }
  2024.         }
  2025.     }
  2026.     }
  2027.     /* Finally, reset supply alarms. */
  2028.     for_all_units(unit) {
  2029.     if (in_play(unit) && unit->plan != NULL) {
  2030.         /* (should probably be a subr) */
  2031.         if (unit->plan->supply_is_low
  2032.         && !past_halfway_point(unit)) {
  2033.         unit->plan->supply_alarm = TRUE;
  2034.         unit->plan->supply_is_low = FALSE;
  2035.             update_unit_display(unit->side, unit, TRUE); 
  2036.         }
  2037.     }
  2038.     }
  2039. }
  2040.  
  2041. static int
  2042. base_production(unit, m)
  2043. Unit *unit;
  2044. int m;
  2045. {
  2046.     int u = unit->type, occprod;
  2047.  
  2048.     if (unit->transport) {
  2049.     occprod = um_occ_production(u, m);
  2050.     return (occprod >= 0 ? occprod : um_base_production(u, m));
  2051.     } else {
  2052.     return um_base_production(u, m);
  2053.     }
  2054. }
  2055.  
  2056. /* Give away supplies, but save enough to stay alive for a couple turns. */
  2057.  
  2058. static void
  2059. try_transfer(from, to, m)
  2060. Unit *from, *to;
  2061. int m;
  2062. {
  2063.     int u = from->type;
  2064.     int oldsupply = from->supply[m];
  2065.  
  2066.     try_transfer_aux(from, to, m);
  2067.     tmpexcess -= (oldsupply - from->supply[m]);
  2068. }
  2069.  
  2070. static void
  2071. try_sharing(from, to, m)
  2072. Unit *from, *to;
  2073. int m;
  2074. {
  2075.     int u = from->type;
  2076.     int oldsupply = from->supply[m];
  2077.   
  2078.     try_transfer_aux(from, to, m);
  2079. }
  2080.  
  2081. /* Material redistribution uses this routine to move supplies around
  2082.    between units far apart or on the same cell. Try to do reasonable
  2083.    things with the materials.  Net producers are much more willing to
  2084.    give away supplies than net consumers. */
  2085.  
  2086. static void
  2087. try_transfer_aux(from, to, m)
  2088. Unit *from, *to;
  2089. int m;
  2090. {
  2091.     int nd, u = from->type, u2 = to->type, fromrate, torate;
  2092.     Unit *occ;
  2093.  
  2094.     if (from != to &&
  2095.     um_inlength(u2, m) >= distance(from->x, from->y, to->x, to->y)) {
  2096.       if (completed(to)) {
  2097.     /* Try for the transfer only if we're below capacity. */
  2098.     if ((nd = um_storage_x(u2, m) - to->supply[m]) > 0) {
  2099.         if ((um_base_production(u, m) > um_base_consumption(u, m))
  2100.         || (survival_time(to) < 3)
  2101.         || (um_storage_x(u, m) * 4 >= um_storage_x(u2, m))) {
  2102.         if (can_satisfy_need(from, m, nd)) {
  2103.             transfer_supply(from, to, m, nd);
  2104.         } else if (can_satisfy_need(from, m, max(1, nd/2))) {
  2105.             transfer_supply(from, to, m, max(1, nd/2));
  2106.         } else if (from->supply[m] > um_storage_x(u, m)) {
  2107.             transfer_supply(from, to, m,
  2108.                     (from->supply[m] - um_storage_x(u, m)));
  2109.         }
  2110.         } else {
  2111.         fromrate = u_speed(u) * um_consumption_per_move(u, m) * 3;
  2112.         fromrate = max(1, fromrate);
  2113.         torate = u_speed(u2) * um_consumption_per_move(u2, m) * 3;
  2114.         torate = max(1, torate);
  2115.         if ((from->supply[m] / fromrate) > (to->supply[m] / torate)) {
  2116.             transfer_supply(from, to, m,
  2117.                     min(nd, (8 + from->supply[m]) / 9));
  2118.         } 
  2119.         }
  2120.     }
  2121.       } else {
  2122.     /* Incomplete units don't need supply, but they are a handy overflow
  2123.        mepository. */
  2124.     if (from->supply[m] > um_storage_x(u, m)
  2125.         && to->supply[m] < um_storage_x(u2, m)) {
  2126.         /* Calculate the limit on how much we can transfer usefully. */
  2127.         nd = min(um_storage_x(u2, m) - to->supply[m],
  2128.              from->supply[m] - um_storage_x(u, m));
  2129.         transfer_supply(from, to, m, nd);
  2130.     }
  2131.       }
  2132.     }
  2133. }
  2134.  
  2135. /* This estimates if a need can be met.  Note that total transfer of requested */
  2136. /* amount is not a good idea, since the supplies might be essential to the */
  2137. /* unit that has them first.  If we're more than half full, or the request */
  2138. /* is less than 1/5 of our supply, then we can spare it. */
  2139.  
  2140. /* (should replace with doctrine/plan controls, check underlying terrain) */
  2141.  
  2142. static int
  2143. can_satisfy_need(unit, m, need)
  2144. Unit *unit;
  2145. int m, need;
  2146. {
  2147.     int supp = unit->supply[m];
  2148.     int stor = um_storage_x(unit->type, m);
  2149.  
  2150.     return (((2 * supp > stor) && (((supp * 4) / 5) > need)) ||
  2151.         (need < stor / 5));
  2152. }
  2153.  
  2154. /* Do everything associated with the end of a turn. */
  2155.  
  2156. static void
  2157. run_turn_end()
  2158. {
  2159.     finish_movement();
  2160.     run_people_consumption();
  2161.     run_cell_consumption();
  2162.     run_unit_base_consumption();
  2163.     run_people_side_changes();
  2164.     /* This should come after other people-related computations,
  2165.        since this only constrains generic overcrowding. */
  2166.     run_people_limits();
  2167.     flush_dead_units();
  2168.     check_post_turn_scores();
  2169.     test_agreements();
  2170.     run_disappearances();
  2171.     if (Debug) report_malloc();
  2172. }
  2173.  
  2174. /* Handle consumption by people. */
  2175.  
  2176. static void
  2177. run_people_consumption()
  2178. {
  2179.     int x, y, m1, m2, t, consum, oldamt, newamt, newtype;
  2180.  
  2181.     /* Precompute whether any people consumption ever happens. */
  2182.     if (any_people_consumption < 0) {
  2183.     int mm1, mm2;
  2184.  
  2185.     any_people_consumption = FALSE;
  2186.     for_all_material_types(mm1) {
  2187.         for_all_material_types(mm2) {
  2188.             if (mm_people_consumption(mm1, mm2) > 0) {
  2189.             any_people_consumption = TRUE;
  2190.             break;
  2191.             }
  2192.         }
  2193.         if (any_people_consumption)
  2194.           break;
  2195.     }
  2196.     Dprintf("Have consumption by people.\n");
  2197.     }
  2198.     if (!any_people_consumption)
  2199.       return;
  2200.     Dprintf("Running people consumption\n");
  2201.     if (any_cell_materials_defined()) {
  2202.     for_all_material_types(m1) {
  2203.         if (cell_material_defined(m1)) {
  2204.         for_all_material_types(m2) {
  2205.             if (cell_material_defined(m2)) {
  2206.             consum = mm_people_consumption(m1, m2);
  2207.             if (consum > 0) {
  2208.                 for_all_cells(x, y) {
  2209.                 oldamt = material_at(x, y, m2);
  2210.                 newamt = oldamt - consum;
  2211.                 if (newamt < 0) {
  2212.                     newamt = 0;
  2213.                     /* Check for exhaustion. */
  2214.                     /* (should share with cell consumption) */
  2215.                     t = terrain_at(x, y);
  2216.                     if (probability(tm_change_on_exhaust(t, m2)) &&
  2217.                     tm_exhaust_type(t, m2) != NONTTYPE) {
  2218.                     newtype = tm_exhaust_type(t, m2);
  2219.                     /* Change the terrain's type. */
  2220.                     set_terrain_at(x, y, newtype);
  2221.                     /* (should) update sides, make units vanish, etc */
  2222.                     }
  2223.                 }
  2224.                 set_material_at(x, y, m2, newamt);
  2225.                 }
  2226.             }
  2227.             }
  2228.         }
  2229.         }
  2230.     }
  2231.     }
  2232. }
  2233.  
  2234. /* Handle consumption by terrain. */
  2235.  
  2236. static void
  2237. run_cell_consumption()
  2238. {
  2239.     int x, y, t, m, consum, oldamt, newamt, willchange, newtype;
  2240.  
  2241.     /* Precompute whether any cell base consumption ever happens. */
  2242.     if (any_cell_consumption < 0) {
  2243.     int t2, m2;
  2244.  
  2245.     any_cell_consumption = FALSE;
  2246.     for_all_terrain_types(t2) {
  2247.         for_all_material_types(m2) {
  2248.             if (tm_consumption(t2, m2) > 0) {
  2249.             any_cell_consumption = TRUE;
  2250.             break;
  2251.             }
  2252.         }
  2253.         if (any_cell_consumption)
  2254.           break;
  2255.     }
  2256.     Dprintf("Have consumption by cells.\n");
  2257.     }
  2258.     if (!any_cell_consumption)
  2259.       return;
  2260.     Dprintf("Running cell consumption\n");
  2261.     if (any_cell_materials_defined()) {
  2262.     for_all_cells(x, y) {
  2263.         t = terrain_at(x, y);
  2264.         willchange = FALSE;
  2265.         for_all_material_types(m) {
  2266.         if (cell_material_defined(m)) {
  2267.             consum = tm_consumption(t, m);
  2268.             oldamt = material_at(x, y, m);
  2269.             newamt = oldamt - consum;
  2270.             if (newamt < 0) {
  2271.             newamt = 0;
  2272.             /* Check for exhaustion. */
  2273.             if (!willchange &&
  2274.                 probability(tm_change_on_exhaust(t, m)) &&
  2275.                 tm_exhaust_type(t, m) != NONTTYPE) {
  2276.                 willchange = TRUE;
  2277.                 newtype = tm_exhaust_type(t, m);
  2278.             }
  2279.             }
  2280.             set_material_at(x, y, m, newamt);
  2281.         }
  2282.         }
  2283.         if (willchange) {
  2284.             /* Change the terrain's type. */
  2285.         set_terrain_at(x, y, newtype);
  2286.         /* (should) update sides, make units vanish, etc */
  2287.         }
  2288.     }
  2289.     }
  2290. }
  2291.  
  2292. /* Handle base consumption by units. */
  2293.  
  2294. static void
  2295. run_unit_base_consumption()
  2296. {
  2297.     Unit *unit;
  2298.  
  2299.     /* Precompute whether any base consumption ever happens. */
  2300.     if (any_unit_base_consumption < 0) {
  2301.     int u, m;
  2302.  
  2303.     any_unit_base_consumption = FALSE;
  2304.     for_all_unit_types(u) {
  2305.         for_all_material_types(m) {
  2306.             if (um_base_consumption(u, m) > 0) {
  2307.             any_unit_base_consumption = TRUE;
  2308.             break;
  2309.             }
  2310.         }
  2311.         if (any_unit_base_consumption)
  2312.           break;
  2313.     }
  2314.     Dprintf("Have consumption by units.\n");
  2315.     }
  2316.     if (!any_unit_base_consumption)
  2317.       return;
  2318.     Dprintf("Running unit consumption\n");
  2319.     for_all_units(unit) {
  2320.     if (is_active(unit)) {
  2321.         unit_consumes(unit);
  2322.     }
  2323.     }
  2324. }
  2325.  
  2326. /* Consume the constant overhead part of supply consumption. */
  2327. /* Usage by movement is subtracted from overhead first. */
  2328.  
  2329. static void
  2330. unit_consumes(unit)
  2331. Unit *unit;
  2332. {
  2333.     int u = unit->type, m, usedup, consump, checkstarve = FALSE;
  2334.  
  2335.     if (alive(unit)) {    
  2336.       for_all_material_types(m) {
  2337.     if (um_base_consumption(u, m) > 0 &&
  2338.         !(unit->transport != NULL && um_consumption_as_occupant(u, m) == 0)) {
  2339.         /* Calculate what was already consumed by movement. */
  2340.         usedup = 0;
  2341.         if (unit->act != NULL)
  2342.           usedup = unit->act->actualmoves * um_consumption_per_move(u, m);
  2343.         consump = um_base_consumption(u, m);
  2344.         /* If being transported, modify the base consumption. */
  2345.         if (unit->transport != NULL)
  2346.           consump = (consump * um_consumption_as_occupant(u, m)) / 100;
  2347.         /* Subtract consumption that was not already used up in movement. */
  2348.         if (usedup < consump)
  2349.           unit->supply[m] -= (consump - usedup);
  2350.         /* Don't let supply go below zero. */
  2351.         if (unit->supply[m] <= 0) {
  2352.         unit->supply[m] = 0;
  2353.         checkstarve = TRUE;
  2354.         }
  2355.     }
  2356.       }
  2357.     }
  2358.     if (checkstarve)
  2359.       maybe_starve(unit, TRUE);
  2360.     if (alive(unit)
  2361.         && unit->plan
  2362.         && !unit->plan->supply_is_low
  2363.         && past_halfway_point(unit)
  2364.         ) {
  2365.         unit->plan->supply_is_low = TRUE;
  2366.         update_unit_display(unit->side, unit, TRUE); 
  2367.     }
  2368. }
  2369.  
  2370. /* What happens to a unit that runs out of supplies.  If it can survive
  2371.    on nothing, then there may be a few turns of grace, depending on
  2372.    how the dice roll... */
  2373.  
  2374. void
  2375. maybe_starve(unit, partial)
  2376. Unit *unit;
  2377. int partial;
  2378. {
  2379.     int u = unit->type, m, starv, oneloss, hploss = 0;
  2380.  
  2381.     for_all_material_types(m) {
  2382.       if (unit->supply[m] <= 0 && !in_supply(unit, m)) {
  2383.     starv = um_hp_per_starve(u, m);
  2384.     if (starv > 0) {
  2385.         oneloss = prob_fraction(starv);
  2386.         hploss = max(hploss, oneloss);
  2387.     }
  2388.       }
  2389.     }
  2390.     if (hploss > 0) {
  2391.       if (hploss >= unit->hp) {
  2392.     /* (should let occupants try to escape first) */
  2393.     kill_unit(unit, H_UNIT_STARVED);
  2394.       } else if (partial) {
  2395.         unit->hp -= hploss;
  2396.         /* (should do other hp loss consequences) */
  2397.     /* (use generic damage routine?) */
  2398.       }
  2399.     }
  2400. }
  2401.  
  2402. /* Check if the unit has ready access to a source of supplies. */
  2403.  
  2404. /* (should be more sophisticated and account for supply lines etc) */
  2405.  
  2406. static int
  2407. in_supply(unit, m)
  2408. Unit *unit;
  2409. int m;
  2410. {
  2411.     if (unit->transport != NULL) {
  2412.         if (unit->transport->supply[m] > 0)
  2413.       return TRUE;
  2414.     }
  2415.     return FALSE;
  2416. }
  2417.  
  2418. /* Some types of units can become completed and grow to full size
  2419.    automatically when they get to a certain point. */
  2420.  
  2421. static void
  2422. run_self_builds()
  2423. {
  2424.     int u, cpper;
  2425.     Unit *unit;
  2426.  
  2427.     if (any_self_builds < 0) {
  2428.     any_self_builds = FALSE;
  2429.     for_all_unit_types(u) {
  2430.         if (u_cp_per_self_build(u) > 0) {
  2431.         any_self_builds = TRUE;
  2432.         break;
  2433.         }
  2434.     }
  2435.     }
  2436.     if (!any_self_builds)
  2437.       return;
  2438.     Dprintf("Running self builds\n");
  2439.     for_all_units(unit) {
  2440.     u = unit->type;
  2441.     if (in_play(unit)
  2442.         && !fullsized(unit)
  2443.         && (cpper = u_cp_per_self_build(u)) > 0
  2444.         && unit->cp >= u_cp_to_self_build(u)) {
  2445.         unit->cp += cpper;
  2446.         if (unit->cp > u_cp(u)) unit->cp = u_cp(u);
  2447.         if (completed(unit)) {
  2448.         make_unit_complete(unit);
  2449.         } else {
  2450.             /* Let the player know that progress was made. */
  2451.         update_unit_display(unit->side, unit, TRUE);
  2452.         }
  2453.     }
  2454.     }
  2455. }
  2456.  
  2457. static void
  2458. run_people_side_changes()
  2459. {
  2460.     int x, y, u, t;
  2461.     Unit *unit;
  2462.  
  2463.     if (!people_sides_defined())
  2464.       return;
  2465.     if (any_people_side_changes < 0) {
  2466.     any_people_surrenders = (int *) xmalloc(numutypes * sizeof(int));
  2467.     any_people_side_changes = FALSE;
  2468.     for_all_unit_types(u) {
  2469.         for_all_terrain_types(t) {
  2470.         if (ut_people_surrender(u, t) > 0) {
  2471.             any_people_side_changes = TRUE;
  2472.             any_people_surrenders[u] = TRUE;
  2473.             break;
  2474.         }
  2475.         }
  2476.     }
  2477.     }
  2478.     if (!any_people_side_changes)
  2479.       return;
  2480.     for_all_cells(x, y) {
  2481.     if (unit_at(x, y) != NULL) {
  2482.         for_all_stack(x, y, unit) {
  2483.         /* The people here may change sides. */
  2484.             u = unit->type;
  2485.         if (any_people_surrenders[u]
  2486.             && probability(people_surrender_chance(u, x, y))) {
  2487.             change_people_side_around(x, y, u, unit->side);
  2488.         }
  2489.         }
  2490.     } else {
  2491.         /* Unoccupied cells might see population revert. */
  2492.         /* (this would need multiple-loyalty pops) */
  2493.     }
  2494.     }
  2495. }
  2496.  
  2497. int
  2498. people_surrender_chance(u, x, y)
  2499. int u, x, y;
  2500. {
  2501.     int m, chance, peop;
  2502.  
  2503.     chance = ut_people_surrender(u, terrain_at(x, y));
  2504.     /* Modify the basic chance according to people types, if present. */
  2505.     if (any_cell_materials_defined()) {
  2506.     for_all_material_types(m) {
  2507.         if (m_people(m) > 0
  2508.         && cell_material_defined(m)) {
  2509.         peop = material_at(x, y, m);
  2510.         if (peop > 0) {
  2511.             chance = (chance * um_people_surrender(u, m)) / 100;
  2512.         }
  2513.         }
  2514.     }
  2515.     }
  2516.     return chance;
  2517. }
  2518.  
  2519. void
  2520. change_people_side_around(x, y, u, side)
  2521. int x, y, u;
  2522. Side *side;
  2523. {
  2524.     int pop = people_side_at(x, y), s = side_number(side), dir, x1, y1;
  2525.  
  2526.     if (pop != NOBODY
  2527.         && pop != s
  2528.         && !trusted_side(side, side_n(pop))) {
  2529.     set_people_side_at(x, y, s);
  2530.     update_cell_display_all_sides(x, y, TRUE);
  2531.     /* (should decrement coverage of previous owner somewhere?) */
  2532.     for_all_directions(dir) {
  2533.         if (interior_point_in_dir(x, y, dir, &x1, &y1)) {
  2534.         update_cell_display_all_sides(x1, y1, TRUE);
  2535.         }
  2536.     }
  2537.     }
  2538.     /* (should be able to do adjacent cells also) */
  2539. }
  2540.  
  2541. /* See if the numbers of individuals in a cell exceeds the max, and migrate or
  2542.    remove so as to bring the numbers back in line. */
  2543.  
  2544. static void
  2545. run_people_limits()
  2546. {
  2547.     int m, t, x, y, num, ratio, amt, newamt;
  2548.     
  2549.     if (any_people_max < 0) {
  2550.     any_people_max = FALSE;
  2551.     for_all_terrain_types(t) {
  2552.         if (t_people_max(t) >= 0) {
  2553.         any_people_max = TRUE;
  2554.         break;
  2555.         }
  2556.     }
  2557.     }
  2558.     if (!any_people_max)
  2559.       return;
  2560.     if (!any_cell_materials_defined())
  2561.       return;
  2562.     for_all_cells(x, y) {
  2563.     t = terrain_at(x, y);
  2564.     if (t_people_max(t) >= 0) {
  2565.         num = num_people_at(x, y);
  2566.         if (num > t_people_max(t)) {
  2567.         /* Too many people here, (should) trim them down. */
  2568.         /* Compute the ratio of limit to actual number.
  2569.            (Note that actual number is guaranteed to be nonzero.) */
  2570.         ratio = (t_people_max(t) * 100) / num;
  2571.         for_all_material_types(m) {
  2572.             if (m_people(m) > 0
  2573.             && cell_material_defined(m)) {
  2574.             amt = material_at(x, y, m);
  2575.             if (amt > 0) {
  2576.                 newamt = (amt * ratio) / 100;
  2577.                 set_material_at(x, y, m, newamt);
  2578.             }
  2579.             }
  2580.         }
  2581.         }
  2582.     }
  2583.     }
  2584. }
  2585.  
  2586. /* (generic routine) */
  2587.  
  2588. int
  2589. num_people_at(x, y)
  2590. int x, y;
  2591. {
  2592.     int m, num;
  2593.  
  2594.     num = 0;
  2595.     for_all_material_types(m) {
  2596.     if (cell_material_defined(m)) {
  2597.         num += material_at(x, y, m) * m_people(m);
  2598.     }
  2599.     }
  2600.     return num;
  2601. }
  2602.  
  2603. static void
  2604. update_cell_display_all_sides(x, y, rightnow)
  2605. int x, y, rightnow;
  2606. {
  2607.     Side *side;
  2608.  
  2609.     for_all_sides(side) {
  2610.     if (side->ingame && (g_see_all() || cover(side, x, y) > 0)) {
  2611.         update_cell_display(side, x, y, rightnow);
  2612.     }
  2613.     }
  2614. }
  2615.  
  2616. /* See if it's time for any scheduled arrivals to appear. */
  2617.  
  2618. static void
  2619. run_appearances()
  2620. {
  2621.     int curturn, nx, ny, nw, nh, nx1, ny1;
  2622.     Obj *appear;
  2623.     Unit *unit, *transport;
  2624.  
  2625.     if (any_appearances < 0) {
  2626.         any_appearances = FALSE;
  2627.     for_all_units(unit) {
  2628.         if (unit->cp < 0 && unit->hook != lispnil) {
  2629.         appear = get_x_property(unit, K_APPEAR);
  2630.         if (appear != lispnil) {
  2631.             any_appearances = TRUE;
  2632.             break;
  2633.         }
  2634.         }
  2635.     }
  2636.     }
  2637.     if (!any_appearances)
  2638.       return;
  2639.     Dprintf("Running appearances\n");
  2640.     curturn = g_turn();
  2641.     for_all_units(unit) {
  2642.         /* See if now time for a unit to appear. */
  2643.         if (unit->cp < 0 && unit->hook != lispnil) {
  2644.         appear = get_x_property(unit, K_APPEAR);
  2645.         if (appear != lispnil && c_number(car(appear)) <= curturn) {
  2646.         /* Set the unit to its correct cp. */
  2647.         unit->cp = (- unit->cp);
  2648.         /* Get the base location at which it will appear. */
  2649.         nx = (- unit->prevx);  ny = (- unit->prevy);
  2650.         if (cdr(appear) != lispnil && numberp(cadr(appear))) {
  2651.             /* Appear at a random location around nx,ny. */
  2652.             nw = c_number(cadr(appear));
  2653.             if (cddr(appear) != lispnil && numberp(caddr(appear))) {
  2654.             nh = c_number(caddr(appear));
  2655.             } else {
  2656.             nh = nw;
  2657.             }
  2658.             if (random_point_in_area(nx, ny, nw, nh, &nx1, &ny1)) {
  2659.             nx = nx1;  ny = ny1;
  2660.             }
  2661.         }
  2662.         /* Do the usual steps to place the unit. */
  2663.         /* (should be able to retry with diff loc if nw or nh > 0) */
  2664.         if (inside_area(nx, ny)) {
  2665.             if (can_occupy_cell(unit, nx, ny)) {
  2666.             enter_cell(unit, nx, ny);
  2667.             } else {
  2668.             /* Search this cell for units to enter. */
  2669.             for_all_stack(nx, ny, transport) {
  2670.                 if (unit->side == transport->side
  2671.                 && can_occupy(unit, transport)) {
  2672.                 enter_transport(unit, transport);
  2673.                 break;
  2674.                 }
  2675.             }
  2676.             /* We got a problem, make the unit wait for next turn;
  2677.                will just try again. */
  2678.             unit->cp = (- unit->cp);
  2679.             }
  2680.         } else {
  2681.             /* loc of reinforcement is messed up */
  2682.         }
  2683.         init_unit_actorstate(unit);
  2684.         init_unit_plan(unit);
  2685.         }
  2686.         }
  2687.     }
  2688. }
  2689.  
  2690. static void
  2691. run_disappearances()
  2692. {
  2693.     int curturn;
  2694.     Obj *disappear;
  2695.     Unit *unit;
  2696.  
  2697.     if (any_disappearances < 0) {
  2698.         any_disappearances = FALSE;
  2699.     for_all_units(unit) {
  2700.         if (unit->hook != lispnil) {
  2701.         disappear = get_x_property(unit, K_DISAPPEAR);
  2702.         if (disappear != lispnil) {
  2703.             any_disappearances = TRUE;
  2704.             break;
  2705.         }
  2706.         }
  2707.     }
  2708.     }
  2709.     if (!any_disappearances)
  2710.       return;
  2711.     Dprintf("Running disappearances\n");
  2712.     curturn = g_turn();
  2713.     for_all_units(unit) {
  2714.         /* See if now time for a unit to disappear. */
  2715.         if (in_play(unit) && unit->hook != lispnil) {
  2716.             disappear = get_x_property(unit, K_DISAPPEAR);
  2717.             if (disappear != lispnil && c_number(car(disappear)) <= curturn) {
  2718.         /* (should eject occupants first if possible) */
  2719.         kill_unit(unit, H_UNIT_KILLED);
  2720.         }
  2721.     }
  2722.     }
  2723. }
  2724.  
  2725. /* Some types of units recover lost hp spontaneously. */
  2726.  
  2727. static void
  2728. run_hp_recovery()
  2729. {
  2730.     int u, hprecovery, hpmax, oldhp;
  2731.     Unit *unit;
  2732.  
  2733.     if (any_hp_recovery < 0) {
  2734.     any_hp_recovery = FALSE;
  2735.         for_all_unit_types(u) {
  2736.         if (u_hp_recovery(u) > 0) {
  2737.         any_hp_recovery = TRUE;
  2738.         break;
  2739.         }
  2740.     }
  2741.     }
  2742.     if (!any_hp_recovery)
  2743.       return;
  2744.     Dprintf("Running hp recovery\n");
  2745.     for_all_units(unit) {
  2746.     if (is_active(unit)) {
  2747.         u = unit->type;
  2748.         hprecovery = u_hp_recovery(u);
  2749.         hpmax = u_hp(u);
  2750.         /* (should only do for one part of multi-part unit?) */
  2751.         if (hprecovery > 0 && unit->hp < hpmax) {
  2752.         oldhp = unit->hp;
  2753.         unit->hp += prob_fraction(hprecovery);
  2754.         if (unit->hp > hpmax) unit->hp = hpmax;
  2755.         /* Inform the player if the unit's hp changed. */
  2756.         if (unit->hp != oldhp) {
  2757.             update_unit_display(unit->side, unit, TRUE);
  2758.         }
  2759.         }
  2760.     }
  2761.     }
  2762. }
  2763.  
  2764. static void
  2765. run_detonation_accidents()
  2766. {
  2767.     int u, t, x, y, z, chance;
  2768.     Unit *unit;
  2769.  
  2770.     if (any_detonation_accidents < 0) {
  2771.     any_detonation_accidents = FALSE;
  2772.     for_all_unit_types(u) {
  2773.         for_all_terrain_types(t) {
  2774.         if (ut_detonation_accident(u, t) > 0) {
  2775.             any_detonation_accidents = TRUE;
  2776.             break;
  2777.         }
  2778.         }
  2779.     }
  2780.     }
  2781.     if (!any_detonation_accidents)
  2782.       return;
  2783.     for_all_units(unit) {
  2784.     if (in_play(unit) && completed(unit)) {
  2785.         x = unit->x;  y = unit->y;  z = unit->z;
  2786.         t = terrain_at(x, y);
  2787.         chance = ut_detonation_accident(unit->type, t);
  2788.         if (chance > 0) {
  2789.             maybe_detonate_accidently(unit);
  2790.         }
  2791.     }
  2792.     }
  2793. }
  2794.  
  2795. static void
  2796. maybe_detonate_accidently(unit)
  2797. Unit *unit;
  2798. {
  2799.     int x = unit->x, y = unit->y, chance, t;
  2800.     extern int maxudetonaterange;
  2801.  
  2802.     t = terrain_at(x, y);
  2803.     chance = ut_detonation_accident(unit->type, t);
  2804.     if (xrandom(10000) < chance) {
  2805.     /* Detonate the unit right where it is. */
  2806.     detonate_unit(unit, x, y, unit->z);
  2807.     reckon_damage_around(x, y, maxudetonaterange);
  2808.     }
  2809. }
  2810.  
  2811. /* Unconditional surrender. */
  2812.  
  2813. void
  2814. resign_game(side, side2)
  2815. Side *side, *side2;
  2816. {
  2817.     /* Nothing to do if we're not in the game. */
  2818.     if (!side->ingame)
  2819.       return;
  2820.     /* Tell everybody about the resignation. */
  2821.     /* (should record an appropriate event, will be textified by event handler) */
  2822.     side_loses(side, side2, -1);
  2823. }
  2824.  
  2825. /* This is true if there is any kind of realtime limit on the game. */
  2826.  
  2827. int
  2828. realtime_game()
  2829. {
  2830.     return (g_rt_for_game() > 0
  2831.             || g_rt_per_side() > 0
  2832.             || g_rt_per_turn() > 0);
  2833. }
  2834.  
  2835. /* Pass NULL to see if all sides are now willing to save the game. */
  2836.  
  2837. int
  2838. all_others_willing_to_save(side)
  2839. Side *side;
  2840. {
  2841.     Side *side2;
  2842.  
  2843.     for_all_sides(side2) {
  2844.     if (side != side2 && !side2->willingtosave)
  2845.       return FALSE; 
  2846.     }
  2847.     return TRUE;
  2848. }
  2849.  
  2850. /* Pass NULL to see if all sides are now willing to declare a draw. */
  2851.  
  2852. int
  2853. all_others_willing_to_quit(side)
  2854. Side *side;
  2855. {
  2856.     Side *side2;
  2857.  
  2858.     for_all_sides(side2) {
  2859.     if (side != side2 && !side2->willingtodraw)
  2860.       return FALSE; 
  2861.     }
  2862.     return TRUE;
  2863. }
  2864.  
  2865. /* This forces an end to the game directly. */
  2866.  
  2867. void
  2868. end_the_game()
  2869. {
  2870.     Side *side;
  2871.  
  2872.     Dprintf("The game is over.\n");
  2873.     record_event(H_GAME_ENDED, ALLSIDES);
  2874.     /* Set the global that indicates the game is over for everybody. */
  2875.     endofgame = TRUE;
  2876.     for_all_sides(side) {
  2877.         /* (should there be any other effects on sides, like final scoring?) */
  2878.         if (side_has_display(side)) {
  2879.             update_turn_display(side, TRUE);
  2880.             update_side_display(side, side, TRUE);
  2881.         }
  2882.     }
  2883.     end_history();
  2884.     dump_statistics();
  2885. }
  2886.